library(ggplot2)
library(tidyverse)
library(GGally)
library(ggpubr)
#load the dataframes for the figure
remove cells in the edges : pos.x > 45 & < 1150 pos.y >
45 & < 1000 ##add the replicate info
aic.df <- aic.df %>%
mutate(exp.field = paste0(str_split(cell.id, "_", simplify = T)[,2],"_",
str_split(cell.id, "_", simplify = T)[,3]),
colony = case_when(exp.field %in% c("20min_s3", "20min_s4") ~ "Replicate 1",
exp.field %in% c("20min_s5", "20min_s6") ~ "Replicate 2",
exp.field %in% c("20min_s7", "20min_s8" , "20min_s9") ~ "Replicate 3"))
aic.df <- aic.df %>%
mutate(colony = ifelse(degron == "stable" & red == "pup1-rfp",
case_when(exp.field %in% c("20min_s4", "20min_s5") ~ "Replicate 1",
exp.field %in% c("20min_s6", "20min_s7") ~ "Replicate 2",
exp.field %in% c("20min_s8", "20min_s9") ~ "Replicate 3"), colony))
# filter(value < 0.05)
##Cellular attributes
pup1.cell.attr <- read_csv("~/plots/all_data/all_pup1_cell_attr.csv")
Rows: 19396 Columns: 29
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): cell.id, degron, red, treatment
dbl (25): gfp.mean.bg.af.sub.new, gfp.sum.bg.af.sub, area, area.puncta, BB_B, BB_C, Elip_B, Elip_C, no.of.voxels, pos.x, pos.y, spheracity, volume, rfp.mean...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
###pup1-RFP background
pup1.cell.attr <- pup1.cell.attr %>%
mutate(exp.field = paste0(str_split(cell.id, "_", simplify = T)[,2],"_",
str_split(cell.id, "_", simplify = T)[,3]),
colony = case_when(exp.field %in% c("20min_s3", "20min_s4") ~ "Replicate 1",
exp.field %in% c("20min_s5", "20min_s6") ~ "Replicate 2",
exp.field %in% c("20min_s7", "20min_s8" , "20min_s9") ~ "Replicate 3"))
pup1.cell.attr <- pup1.cell.attr %>%
mutate(colony = ifelse(degron == "stable" & red == "pup1-rfp",
case_when(exp.field %in% c("20min_s4", "20min_s5") ~ "Replicate 1",
exp.field %in% c("20min_s6", "20min_s7") ~ "Replicate 2",
exp.field %in% c("20min_s8", "20min_s9") ~ "Replicate 3"), colony))
#removing the 40min and 60min experiments from the stable gfp experiments
pup1.cell.attr <- pup1.cell.attr %>%
mutate(exp = str_split(exp.field, "_", simplify = T)[,1]) %>%
filter(exp == "20min")
Adding the gfp.sum column for the stable GFP experiment
pup1.cell.attr <- read_csv("~/plots/pup1-rfp-gfp-decay/4-28-21-8hrGFP/data/gfp_stable_filtered.csv") %>%
filter(image.no == 1) %>%
dplyr::select(cell.id, gfpSumBgAFsub) %>%
mutate(cell.id = paste0(cell.id,"_","stable_pup1-rfp_none")) %>%
dplyr::rename("gfp.sum.bg.af.sub" = "gfpSumBgAFsub") %>%
left_join(pup1.cell.attr %>%
filter(degron == "stable") %>%
dplyr::select(-gfp.sum.bg.af.sub),., by = "cell.id") %>%
bind_rows(pup1.cell.attr %>%
filter(degron != "stable"),.)
removing multiple entries of the cell because some cell have more
than
multiple.pup1 <- pup1.cell.attr %>%
mutate(dapi.mean.bg.sub.puncta = ifelse(is.na(dapi.mean.bg.sub.puncta), 0, dapi.mean.bg.sub.puncta) ,
rfp.mean.bg.sub.puncta = ifelse(is.na(rfp.mean.bg.sub.puncta), 0 , rfp.mean.bg.sub.puncta)) %>%
filter(rfp.mean.bg.sub.puncta > 0) %>%
group_by(cell.id) %>%
tally() %>%
filter(n>1)
pup1.cell.attr<- pup1.cell.attr %>%
group_by(cell.id) %>%
mutate(rfp.mean.bg.sub.puncta = ifelse(cell.id %in% multiple.pup1$cell.id , mean(rfp.mean.bg.sub.puncta), rfp.mean.bg.sub.puncta),
rfp.sum.bg.sub.puncta = ifelse(cell.id %in% multiple.pup1$cell.id, sum(rfp.mean.bg.sub.puncta), rfp.sum.bg.sub.puncta)) %>%
distinct(cell.id, .keep_all = TRUE)
#proteasome inhibition experiments
protInhi.attr <- read_csv("~/plots/all_data/all_mg135_attr.csv") %>%
rename("cell.id" = "unique.trackID") %>%
filter(timepoint == 1) %>%
mutate(cell.id = paste0(cell.id ,"_",degron,"_",red,"_",treatment)) %>%
mutate(exp.field = paste0(str_split(cell.id, "_", simplify = T)[,2],"_",
str_split(cell.id, "_", simplify = T)[,3]),
colony = case_when(exp.field %in% c("20min_s3", "20min_s4") ~ "Replicate 1",
exp.field %in% c("20min_s5", "20min_s6") ~ "Replicate 2",
exp.field %in% c("20min_s7", "20min_s8" , "20min_s9") ~ "Replicate 3"))
multiple.proInh <- protInhi.attr %>%
mutate(dapi.mean.bg.sub.puncta = ifelse(is.na(dapi.mean.bg.sub.puncta), 0, dapi.mean.bg.sub.puncta) ,
rfp.mean.bg.sub.puncta = ifelse(is.na(rfp.mean.bg.sub.puncta), 0 , rfp.mean.bg.sub.puncta)) %>%
filter(rfp.mean.bg.sub.puncta > 0) %>%
group_by(cell.id) %>%
tally() %>%
filter(n>1)
protInhi.attr <- protInhi.attr %>%
group_by(cell.id) %>%
mutate(rfp.mean.bg.sub.puncta = ifelse(cell.id %in% multiple.proInh$cell.id , mean(rfp.mean.bg.sub.puncta), rfp.mean.bg.sub.puncta),
rfp.sum.bg.sub.puncta = ifelse(cell.id %in% multiple.proInh$cell.id, sum(rfp.mean.bg.sub.puncta), rfp.sum.bg.sub.puncta)) %>%
distinct(cell.id, .keep_all = TRUE)
Adding the protein inhibition experiment data
pup1.proInhi.attr <- pup1.cell.attr %>%
bind_rows(.,protInhi.attr %>%
dplyr::select(-time,
-timepoint,
-image.no,
-ln.gfp,
-ln.gfp.dif,
-trackID,
-gfp.intensity.center,
-gfp.int.mean,
-gfp.int.median,
-gfp.int.sum,
-no.of.triangles,
-field,
-time.dif.gfp,
-real.time.gfp,
-sample,
-avg.gfp.bg,
-Min_gfp,
-gfp.mean.bg.sub,
-value,
-t80,
-t95,
-threshold,
-threshold_95,
-gfp.mean.bg.af.sub,
-threshold_80,
-Mean_gfp,
-image,
-experiment,
-gfp.sum.bg.sub))
#keeping the dy.dm model parameters
#only dy.dm
dy.pup1.rep1.mat <- aic.df %>%
filter(red == "pup1-rfp") %>%
filter(ifelse(degron %in% c("stable","stable.2","stable.3"), dy < 0.1, dy < 0.5)) %>%
group_by(cell.id) %>%
filter(model == "dy.dm") %>%
mutate(dm = ifelse(is.na(dm), Inf, dm)) %>%
filter( dm > 0.000015)
#count the number of cells in each experiment
dy.pup1.rep1.mat %>% group_by(degron, treatment) %>% tally()
#creating the df for the MLR
mlr.df <- dy.pup1.rep1.mat %>%
#left join with the df with cellular attributes
left_join(.,pup1.proInhi.attr, by = c("cell.id","red","treatment","degron", "exp.field","colony")) %>%
#remove cells with no rfp puncta info
mutate(rfp.mean.bg.sub.puncta = ifelse(is.na(rfp.mean.bg.sub.puncta), 0, rfp.mean.bg.sub.puncta)) %>%
filter(rfp.mean.bg.sub.puncta > 0)
#checking how many cells there are in each experiment
mlr.df %>% group_by(degron, treatment) %>% tally()
#looking the placement of single cells in images

##Removing the columns that I wont regress upon
mlr.df <- mlr.df %>%
filter(pos.x > 45 & pos.x < 1150,
pos.y > 45 & pos.y < 1000) %>%
dplyr::select(-f,
-rfp.mean.af.sub.puncta,
-rfp.sum.af.sub.puncta,
-dapi.sum.af.sub.puncta,
-dapi.mean.af.sub.puncta,
-model,
-k,
-fevals,
-gevals,
-niter,
-convcode,
-kkt1,
-kkt2,
-value,
-xtime,
# -treatment,
-rfp.mean.bg.sub,
-rfp.sum.bg.sub,
-dapi.mean.bg.sub,
-dapi.sum.bg.sub,
-dapi.mean.bg.sub.puncta,
-area.puncta,
-BB_B,
-BB_C,
-pos.x,
-pos.y,
-gfp.sum.bg.af.sub,
-rfp.sum.bg.sub.puncta,
-no.of.voxels,
-volume,
-spheracity) %>%
mutate(shape = Elip_B/Elip_C,
t.half = log(2)/dy) %>%
ungroup() %>%
dplyr::select(-cell.id,
-red,
-exp.field,
-aic,
-Elip_B,
-Elip_C,
-exp)
#Regressors to use for MLR
regressors <- c("dm",
"gfp.mean.bg.af.sub.new",
# "gfp.sum.bg.af.sub",
"area",
# "no.of.voxels",
# "spheracity",
# "volume",
"rfp.mean.bg.sub.puncta",
# "rfp.sum.bg.sub.puncta",
"dapi.sum.bg.sub.puncta",
"shape")
Function to evaluate step R
stepR.fn <- function(reg, df, prt.inh.trt, id.var) {
#get the estimates
stepR.est <-
lapply(reg, function(a) {
#regressors to remove one by one
temp.df2 <- df %>%
dplyr::select(all_of(reg),
degron,
t.half,
# dy,
colony,
treatment) %>% #removed t.half and replaced with dy
ungroup() %>%
dplyr::select(-a)
temp.df2 %>%
filter(treatment %in% prt.inh.trt) %>%
split(.[id.var]) %>%
map(., function(b) {
lm(t.half ~ .,
data = b %>% dplyr::select(-degron, -colony, -treatment)) %>%
broom::tidy()
}) %>%
bind_rows(.id = id.var) %>%
mutate(removed.col = a)
}) %>%
bind_rows()
#get the stats of the model
stepR.glance <- lapply(reg, function(a) {
temp.df2 <- df %>%
dplyr::select(all_of(reg), degron, t.half,
# dy,
colony, treatment) %>% #removed t.half and replaced with dy
dplyr::select(-a)
temp.df2 %>%
filter(treatment %in% prt.inh.trt) %>%
split(.[id.var]) %>%
map(., function(b) {
lm(t.half ~ .,
data = b %>% dplyr::select(-degron,-colony,-treatment)) %>%
broom::glance()
}) %>%
bind_rows(.id = id.var) %>%
mutate(removed.col = a)
}) %>%
bind_rows()
#get the fits
stepR.fit <- lapply(reg, function(a) {
temp.df2 <- df %>%
dplyr::select(all_of(reg), degron, t.half,
# dy,
colony, treatment) %>% #removed t.half and replaced with dy
dplyr::select(-a)
temp.df2 %>%
filter(treatment %in% prt.inh.trt) %>%
split(.[id.var]) %>%
map(., function(b) {
lm(t.half ~ .,
data = b %>% dplyr::select(-degron, -colony,-treatment))
})
})
#output
stepR.list <- list(stepR.est,
stepR.glance,
stepR.fit)
names(stepR.list) <- c("stepR.est",
"stepR.glance",
"stepR.fit")
return(stepR.list)
}
function to evaluate the full model
fullMLR.fn <- function(regressors, df, prt.inh.trt, id.var) {
#statistics
fullR.glance <- df %>%
ungroup() %>%
filter(treatment %in% prt.inh.trt) %>%
dplyr::select(all_of(regressors),
degron,
t.half,
# dy,
colony,
treatment) %>% #removed t.half and replaced with dy
split(.[id.var]) %>%
map(., function(b) {
lm(t.half ~ .,
data = b %>% dplyr::select(-degron, -colony, -treatment)) %>%
broom::glance()
}) %>%
bind_rows(.id = id.var) %>%
mutate(removed.col = "none")
#estimates
fullR.est <- df %>%
ungroup() %>%
filter(treatment %in% prt.inh.trt) %>%
dplyr::select(all_of(regressors),
degron,
t.half,
# dy,
colony,
treatment) %>% #removed t.half and replaced with dy
split(.[id.var]) %>%
map(., function(b) {
lm(t.half ~ .,
data = b %>% dplyr::select(-degron, -colony,-treatment)) %>%
broom::tidy()
}) %>%
bind_rows(.id = id.var) %>%
mutate(removed.col = "none")
#fits
fullMLR.fit <- df %>%
ungroup() %>%
filter(treatment %in% prt.inh.trt) %>%
dplyr::select(all_of(regressors),
degron,
t.half,
# dy,
colony,
treatment) %>% #removed t.half and replaced with dy
split(.[id.var]) %>%
map(., function(b) {
lm(t.half ~ .,
data = b %>% dplyr::select(-degron, -colony, -treatment))
})
#output
fullMLR.list <- list(fullR.glance,
fullR.est,
fullMLR.fit)
names(fullMLR.list) <- c("fullR.glance",
"fullR.est",
"fullMLR.fit")
return(fullMLR.list)
}
#df where the two experiments of cln2 and stable-GFP are clubbed
mlr.df2 <- mlr.df %>%
filter(degron %in% c("cln2.3","mODC.2","stable.3","stable.2","cln2.4")) %>%
mutate(degron = case_when(degron %in% c("cln2.3","cln2.2","cln2","cln2.4") ~ "yeGFP-CLN2",
degron %in% c("mODC.2", "mODC") ~ "yeGFP-mODC",
degron %in% c("stable","stable.2","stable.3") ~ "yeGFP"))
step MLR estimates #without the protein inhibition
stepR.list <- stepR.fn(reg = regressors,
df = mlr.df2,
prt.inh.trt = "none",
id.var = "degron")
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(a)` instead of `a` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
fullR.list <- fullMLR.fn(reg = regressors,
df = mlr.df2,
prt.inh.trt = "none",
id.var = "degron")
#2D correlation plots
lapply(regressors[1], function(a){
mlr.df %>%
filter(treatment != "none") %>%
mutate(t.half = log(2)/dy) %>%
# filter(degron %in% c("stable.2","stable.3")) %>%
# filter(!(degron %in% c("mODC","cln2.2","cln2","stable"))) %>%
# filter(treatment %in% c("dmso1","dmso2")) %>% %>%
ggplot(.,aes(y = t.half, x = .[[a]]))+
geom_point()+
stat_cor()+
# stat_regline_equation()+
facet_wrap(~treatment , scales = "free")+
labs(title = a)+
scale_x_log10()
})
[[1]]
Warning: Use of `.[[a]]` is discouraged. Use `.data[[a]]` instead.
Warning: Use of `.[[a]]` is discouraged. Use `.data[[a]]` instead.

#y~x + c single variable regression single regressor statistics
stepR.glance <- lapply(regressors, function(a){
temp.df2 <- mlr.df %>%
ungroup() %>%
dplyr::select(-a, -dy)
temp.df2 %>%
filter(treatment == "none") %>%
split(list(.$degron)) %>%
map(.,function(b){
lm(t.half ~ ., data = b %>% dplyr::select(-degron,-colony,-treatment)) %>%
broom::glance()
}) %>%
bind_rows(.id = "degron") %>%
mutate(removed.col = a)
}) %>%
bind_rows()
stepR.glance.dmso <- lapply(regressors, function(a){ #regressors to remove one by one
temp.df2 <- mlr.df %>%
ungroup() %>%
dplyr::select(-a, -dy)
temp.df2 %>%
filter(treatment %in% c("dmso1","dmso2")) %>%
split(list(.$degron, .$treatment)) %>%
map(.,function(b){
lm(t.half ~ ., data = b %>% dplyr::select(-degron, -colony, -treatment)) %>%
broom::glance()
}) %>%
bind_rows(.id = "degron") %>%
mutate(removed.col = a)
}) %>%
bind_rows()
single regressor estimates
stepR.1var.est <- lapply(regressors, function(a){
temp.df2 <- temp.df %>%
ungroup() %>%
dplyr::select(a, t.half,degron)
temp.df2 %>%
split(.$degron) %>%
map(.,function(b){
lm(t.half ~ ., data = b %>% dplyr::select(-degron)) %>%
broom::tidy()
}) %>%
bind_rows(.id = "degron") %>%
mutate(single.col = a)
}) %>%
bind_rows()
#fits
stepR.1var.fit <- lapply(regressors, function(a){
temp.df2 <- mlr.df %>%
ungroup() %>%
dplyr::select(a, t.half,degron)
temp.df2 %>%
split(.$degron) %>%
map(.,function(b){
lm(t.half ~ ., data = b %>% dplyr::select(-degron))
})
})
#testing for one degron
fullMLR.fit <- temp.df %>%
ungroup() %>%
dplyr::select(all_of(regressors), degron,t.half,colony) %>%
split(list(.$degron)) %>%
map(.,function(b){
lm(t.half ~ ., data = b %>% dplyr::select(-degron,-colony))
})
Error in `dplyr::select()`:
! Can't subset columns that don't exist.
✖ Column `gfp.sum.bg.af.sub` doesn't exist.
Backtrace:
1. ... %>% ...
5. dplyr:::select.data.frame(...)
8. tidyselect::eval_select(expr(c(...)), .data)
9. tidyselect:::eval_select_impl(...)
18. tidyselect:::vars_select_eval(...)
...
21. tidyselect:::reduce_sels(node, data_mask, context_mask, init = init)
22. tidyselect:::walk_data_tree(new, data_mask, context_mask)
23. tidyselect:::as_indices_sel_impl(...)
24. tidyselect:::as_indices_impl(x, vars, call = call, strict = strict)
25. tidyselect:::chr_as_locations(x, vars, call = call)
#plotting the difference in r2 (full model - dropout model)
deltaR2.plt.all <- bind_rows(fullR.list$fullR.glance, stepR.list$stepR.glance) %>%
mutate(adj.r.squared = round(adj.r.squared , digits = 4)) %>%
# separate(.,degron, into = c("degron","colony"), sep = ".Replicate ") %>%
# filter(p.value < 0.05) %>%
# group_by(degron, removed.col) %>%
dplyr::select(degron, r.squared, removed.col) %>%
pivot_wider(values_from = r.squared, names_from = removed.col) %>%
rename("Rate of Maturation" = "dm",
"GFP" = "gfp.mean.bg.af.sub.new",
"Area" = "area",
"Pup1-tDimer2" = "rfp.mean.bg.sub.puncta",
"DAPI" = "dapi.sum.bg.sub.puncta",
"Shape" = "shape") %>%
pivot_longer(cols = 3:8) %>%
mutate(value.ratio = value/ none,
value.sub = none - value) %>%
# filter(degron %in% c("cln2.3","mODC.2","stable.3","stable.2","cln2.4")) %>%
# mutate(degron = case_when(degron %in% c("cln2.3","cln2.2","cln2","cln2.4") ~ "GFP-CLN2",
# degron %in% c("mODC.2", "mODC") ~ "GFP-mODC",
# degron %in% c("stable","stable.2","stable.3") ~ "yeGFP"),
# degron = factor(degron , levels = c("GFP-mODC","GFP-CLN2","yeGFP"))) %>%
mutate(degron = factor(degron , levels = c("yeGFP-mODC","yeGFP-CLN2","yeGFP"))) %>%
ggplot(.,aes(y = name, x = value.sub))+
geom_col(width = 0.2)+
facet_wrap(~degron, scales = "free")+
scale_y_discrete(labels = function(x) str_wrap(x, width = 10))+
xlab(TeX("$Delta(r^{2}_{full} - r^{2}_{step})"))+
ylab("Regressor Dropped")+
theme_pubr()+
theme(text = element_text(size = 8),
strip.background = element_blank(),
axis.text.x = element_text(angle = 30))
deltaR2.plt.all

#transform dm and dapi intensity
stepR.list.trans <- stepR.fn(reg = regressors,
df = mlr.df2 %>%
mutate(dm = log10(dm)),
prt.inh.trt = "none",
id.var = "degron")
fullR.list.trans <- fullMLR.fn(reg = regressors,
df = mlr.df2 %>%
mutate(dm = log10(dm)),
prt.inh.trt = "none",
id.var = "degron")

#look at the sign of the estimates
lm(t.half ~ rfp.mean.bg.sub.puncta + dm + gfp.mean.bg.af.sub.new + dapi.sum.bg.sub.puncta, data = mlr.df2 %>% filter(degron == "GFP-mODC"))
Call:
lm(formula = t.half ~ rfp.mean.bg.sub.puncta + dm + gfp.mean.bg.af.sub.new +
dapi.sum.bg.sub.puncta, data = mlr.df2 %>% filter(degron ==
"GFP-mODC"))
Coefficients:
(Intercept) rfp.mean.bg.sub.puncta dm gfp.mean.bg.af.sub.new dapi.sum.bg.sub.puncta
5.467e+00 -6.682e-03 6.376e-04 4.482e-03 1.647e-05
#residual analysis of the models
#residual plots against the fitted values
fullMLR.fit %>%
map(.,autoplot)
$cln2
$cln2.2
$cln2.3
$cln2.4
$mODC
$mODC.2
$stable
$stable.2
$stable.3









Observations: from the residual vs fitted plots: For the degron GFPs
the residual vs the fitted plot lies around the horizonttal band around
0. but for stable GFP, the residual plot is an open funnel shape.
According to page 139 in the intro to linear regression: The patterns in
panels b and c indicate that the variance of the errors is not constant.
The outward-opening funnel pattern in panel b implies that the variance
is an increasing function of y. From the residuals vs regressors plots:
in yeGFP: there is a strong funnel shape with the GFP intensity:
residuals is negatively related to the GFP intensity.
#t.half vs dm
mlr.df %>%
ggplot(.,aes(x = dm, y = dy))+
geom_point()+
facet_wrap(~degron, scales = "free")+
scale_x_log10()
testing multiple colinearity using the full model method = variance
inflation factors. vif > 5 for a regressor is problematic
library(car)
fullR.list$fullMLR.fit %>% map(.,vif)
#only the gfp, rfp, dapi regrrssors
regressors.fp <- c("gfp.mean.bg.af.sub.new",
"rfp.mean.bg.sub.puncta",
"dapi.sum.bg.sub.puncta")
stepR.fp.list <- stepR.fn(reg = regressors.fp,
df = mlr.df2,
prt.inh.trt = "none",
id.var = "degron")
fullR.fp.list <- fullMLR.fn(regressors = regressors.fp,
df = mlr.df2,
prt.inh.trt = "none",
id.var = "degron")
#variance inflation factor
vif(full.fp.fit$cln2.3)
gfp.mean.bg.af.sub.new rfp.mean.bg.sub.puncta dapi.sum.bg.sub.puncta
1.085858 1.833896 1.928188
vif(full.fp.fit$cln2.4)
gfp.mean.bg.af.sub.new rfp.mean.bg.sub.puncta dapi.sum.bg.sub.puncta
1.024273 1.505917 1.477058
vif(full.fp.fit$mODC.2)
gfp.mean.bg.af.sub.new rfp.mean.bg.sub.puncta dapi.sum.bg.sub.puncta
1.001611 1.808745 1.807391
vif(full.fp.fit$stable.3)
gfp.mean.bg.af.sub.new rfp.mean.bg.sub.puncta dapi.sum.bg.sub.puncta
1.008558 1.181293 1.172121
vif(full.fp.fit$stable.2)
gfp.mean.bg.af.sub.new rfp.mean.bg.sub.puncta dapi.sum.bg.sub.puncta
1.008374 1.427904 1.437518
#delta r2 for only the fluorescent proteins as the regressors
deltaR2.plt <- bind_rows(fullR.fp.list$fullR.glance, stepR.fp.list$stepR.glance) %>%
mutate(adj.r.squared = round(adj.r.squared , digits = 4)) %>%
# separate(.,degron, into = c("degron","colony"), sep = ".Replicate ") %>%
# filter(p.value < 0.05) %>%
# group_by(degron, removed.col) %>%
dplyr::select(degron, r.squared, removed.col) %>%
pivot_wider(values_from = r.squared, names_from = removed.col) %>%
rename("GFP intensity" = "gfp.mean.bg.af.sub.new",
"Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
"Total DAPI Int." = "dapi.sum.bg.sub.puncta") %>%
pivot_longer(cols = 3:5) %>%
mutate(value.ratio = value/ none,
value.sub = none - value) %>%
# filter(degron %in% c("cln2.3","mODC.2","stable.3","stable.2","cln2.4")) %>%
# mutate(degron = case_when(degron %in% c("cln2.3","cln2.2","cln2","cln2.4") ~ "GFP-CLN2",
# degron %in% c("mODC.2", "mODC") ~ "GFP-mODC",
# degron %in% c("stable","stable.2","stable.3") ~ "yeGFP"),
# degron = factor(degron , levels = c("GFP-mODC","GFP-CLN2","yeGFP"))) %>%
mutate(degron = factor(degron , levels = c("yeGFP-mODC","yeGFP-CLN2","yeGFP"))) %>%
ggplot(.,aes(y = name, x = value.sub))+
geom_col(width = 0.2)+
facet_wrap(~degron, scales = "free")+
theme(text = element_text(size = 8))+
# scale_x_log10()+
xlab(TeX("$Delta(r^{2}_{full} - r^{2}_{step})"))+
ylab("Regressor Dropped")+
theme_pubr()+
theme(text = element_text(size = 8))
deltaR2.plt

#response == dy instead of t.half
bind_rows(fullR.fp.list$fullR.glance, stepR.fp.list$stepR.glance) %>%
mutate(adj.r.squared = round(adj.r.squared , digits = 4)) %>%
# separate(.,degron, into = c("degron","colony"), sep = ".Replicate ") %>%
filter(p.value < 0.05) %>%
# group_by(degron, removed.col) %>%
select(degron, r.squared, removed.col) %>%
pivot_wider(values_from = r.squared, names_from = removed.col) %>%
rename("GFP intensity" = "gfp.mean.bg.af.sub.new",
"Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
"Total DAPI Int." = "dapi.sum.bg.sub.puncta") %>%
pivot_longer(cols = 3:5) %>%
mutate(value.ratio = value/ none,
value.sub = none - value) %>%
filter(degron %in% c("cln2.3","mODC.2","stable.3","stable.2","cln2.4")) %>%
# mutate(degron = case_when(degron %in% c("cln2.3","cln2.2","cln2","cln2.4") ~ "GFP-CLN2",
# degron %in% c("mODC.2", "mODC") ~ "GFP-mODC",
# degron %in% c("stable","stable.2","stable.3") ~ "yeGFP"),
# degron = factor(degron , levels = c("GFP-mODC","GFP-CLN2","yeGFP"))) %>%
# mutate(degron = factor(degron , levels = c("GFP-mODC","GFP-CLN2","yeGFP"))) %>%
ggplot(.,aes(y = name, x = value.sub))+
geom_col(width = 0.2)+
facet_wrap(~degron, scales = "free")+
theme(text = element_text(size = 8))+
# scale_x_log10()+
xlab(TeX("$Delta(r^{2}_{full} - r^{2}_{step})"))+
ylab("Regressor Dropped")+
theme_pubr()+
theme(text = element_text(size = 8))
Warning: Removed 1 rows containing missing values (position_stack).

#With the protein inhibitors
#with 6 regressors
stepR.prtInh.list <- stepR.fn(reg = regressors,
df = mlr.df,
prt.inh.trt = c("dmso1","dmso2","1uM","2.5uM","5uM","50uM"),
id.var = "treatment")
fullR.prtInh.list <- fullMLR.fn(reg = regressors,
df = mlr.df,
prt.inh.trt = c("dmso1","dmso2","1uM","2.5uM","5uM","50uM"),
id.var = "treatment")
#with just fluorecent proteins
stepR.prtInh.fp.list <- stepR.fn(reg = regressors.fp,
df = mlr.df,
prt.inh.trt = c("dmso1","dmso2","1uM","2.5uM","5uM","50uM"),
id.var = "treatment")
fullR.prtInh.fp.list <- fullMLR.fn(reg = regressors.fp,
df = mlr.df,
prt.inh.trt = c("dmso1","dmso2","1uM","2.5uM","5uM","50uM"),
id.var = "treatment")
plots
#with 6 regressors
bind_rows(fullR.prtInh.list$fullR.glance, stepR.prtInh.list$stepR.glance) %>%
mutate(adj.r.squared = round(adj.r.squared , digits = 4)) %>%
select(treatment, r.squared, removed.col) %>%
pivot_wider(values_from = r.squared, names_from = removed.col) %>%
pivot_longer(cols = 3:8) %>%
mutate(value.ratio = value/ none,
value.sub = none - value) %>%
ggplot(.,aes(y = name, x = value.sub))+
geom_col()+
facet_wrap(~factor(treatment, levels = c("dmso1","dmso2","1uM","2.5uM","5uM","50uM")), scales = "free")+
theme(text = element_text(size = 8))+
# scale_x_log10()+
xlab(TeX("$Delta(r^{2}_{full} - r^{2}_{step})"))+
ylab("regressor dropped")
#with 3 fluorescent proteins
bind_rows(fullR.prtInh.fp.list$fullR.glance, stepR.prtInh.fp.list$stepR.glance) %>%
mutate(adj.r.squared = round(adj.r.squared , digits = 4)) %>%
select(treatment, r.squared, removed.col) %>%
pivot_wider(values_from = r.squared, names_from = removed.col) %>%
pivot_longer(cols = 3:5) %>%
mutate(value.ratio = value/ none,
value.sub = none - value) %>%
ggplot(.,aes(y = name, x = value.sub))+
geom_col()+
facet_wrap(~factor(treatment, levels = c("dmso1","dmso2","1uM","2.5uM","5uM","50uM")), scales = "free")+
theme(text = element_text(size = 8))+
# scale_x_log10()+
xlab(TeX("$Delta(r^{2}_{full} - r^{2}_{step})"))+
ylab("regressor dropped")
#looked at the outliers
lapply(fullMLR.fit, function(a){
cooks.distance(a) %>%
broom::tidy() %>%
arrange(desc(x))
})
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
$cln2
$cln2.2
$cln2.3
$cln2.4
$mODC
$mODC.2
$stable
$stable.2
$stable.3
NA
cooks.distance(fullMLR.fit$cln2.3) %>% broom::tidy() %>% arrange(desc(x))
Warning: 'tidy.numeric' is deprecated.
See help("Deprecated")
lapply(fullMLR.fit, summary)
#df to be used with step function
temp.df.list <- mlr.df2 %>%
filter(treatment == "none") %>%
# mutate( dm = log10(dm)) %>%
split(.$degron)
#using stepAIC from MASS
full.stepAIC.mass %>% map(.,broom::tidy)
$`GFP-CLN2`
$`GFP-mODC`
$yeGFP
NA
#step AIC with all the fp markers + cell shape
full.stepAIC <- lapply(temp.df.list, function(a){
n <- nrow(a)
step(lm(t.half ~ ., data = a %>%
dplyr::select(regressors,
t.half,
-dy,
-treatment)),
direction = "backward",
trace = T,
# k = log(n),
k =2 ) #k = 2 when small dataset and k = log(n) where n = no. of observations for when the dataset is large
})
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(regressors)` instead of `regressors` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
Start: AIC=5023.53
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta + shape
Df Sum of Sq RSS AIC
- rfp.mean.bg.sub.puncta 1 32.7 36232 5023.0
- shape 1 38.8 36239 5023.3
- area 1 39.3 36239 5023.3
<none> 36200 5023.5
- dm 1 247.6 36447 5032.5
- dapi.sum.bg.sub.puncta 1 918.2 37118 5061.8
- gfp.mean.bg.af.sub.new 1 7805.7 44006 5335.7
Step: AIC=5022.98
t.half ~ dm + gfp.mean.bg.af.sub.new + area + dapi.sum.bg.sub.puncta +
shape
Df Sum of Sq RSS AIC
- shape 1 37.2 36270 5022.6
<none> 36232 5023.0
- area 1 89.4 36322 5024.9
- dm 1 259.8 36492 5032.5
- dapi.sum.bg.sub.puncta 1 970.8 37203 5063.5
- gfp.mean.bg.af.sub.new 1 7803.3 44036 5334.8
Step: AIC=5022.63
t.half ~ dm + gfp.mean.bg.af.sub.new + area + dapi.sum.bg.sub.puncta
Df Sum of Sq RSS AIC
<none> 36270 5022.6
- area 1 82.2 36352 5024.3
- dm 1 249.7 36519 5031.7
- dapi.sum.bg.sub.puncta 1 1048.1 37318 5066.5
- gfp.mean.bg.af.sub.new 1 7848.3 44118 5335.8
Start: AIC=1261.28
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta + shape
Df Sum of Sq RSS AIC
- shape 1 1.67 3519.1 1260.1
- dm 1 2.15 3519.6 1260.3
<none> 3517.5 1261.3
- rfp.mean.bg.sub.puncta 1 5.47 3522.9 1261.8
- area 1 85.84 3603.3 1299.2
- dapi.sum.bg.sub.puncta 1 89.54 3607.0 1300.9
- gfp.mean.bg.af.sub.new 1 479.97 3997.4 1471.2
Step: AIC=1260.06
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta
Df Sum of Sq RSS AIC
- dm 1 2.17 3521.3 1259.1
<none> 3519.1 1260.1
- rfp.mean.bg.sub.puncta 1 5.05 3524.2 1260.4
- area 1 84.64 3603.8 1297.4
- dapi.sum.bg.sub.puncta 1 87.90 3607.0 1298.9
- gfp.mean.bg.af.sub.new 1 482.37 4001.5 1470.9
Step: AIC=1259.08
t.half ~ gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta
Df Sum of Sq RSS AIC
<none> 3521.3 1259.1
- rfp.mean.bg.sub.puncta 1 5.13 3526.4 1259.5
- area 1 85.97 3607.3 1297.0
- dapi.sum.bg.sub.puncta 1 87.30 3608.6 1297.7
- gfp.mean.bg.af.sub.new 1 493.27 4014.6 1474.3
Start: AIC=922.36
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta + shape
Df Sum of Sq RSS AIC
<none> 2628.7 922.36
- shape 1 7.60 2636.3 924.18
- area 1 49.53 2678.2 945.06
- rfp.mean.bg.sub.puncta 1 56.77 2685.5 948.63
- dapi.sum.bg.sub.puncta 1 93.01 2721.7 966.37
- dm 1 105.69 2734.4 972.52
- gfp.mean.bg.af.sub.new 1 561.29 3190.0 1176.40
full.stepAIC %>%
map(., broom::glance) %>%
bind_rows(.id = "sample")
# filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3"))
full.stepAIC %>%
map(., broom::tidy)
$yeGFP
$`yeGFP-CLN2`
$`yeGFP-mODC`
# bind_rows(.id = "sample") %>%
# filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3"),
# p.value < 0.05) %>%
full.stepAIC %>%
map(.,function(a){
a$anova
}) %>%
bind_rows(.,.id = "degron") %>%
mutate(Step = as.character(Step),
Step = ifelse(Step == "", "Full",Step)) %>%
group_by(degron) %>%
mutate(del.aic = AIC[1]-AIC)
full.stepAIC.fp %>%
map(.,function(a){
a$anova
}) %>%
bind_rows(.,.id = "degron") %>%
mutate(Step = as.character(Step),
Step = ifelse(Step == "", "Full",Step)) %>%
group_by(degron) %>%
mutate(del.aic = AIC[1]-AIC)
NA
NA
#Plot the aic difference at each step
full.stepAIC %>%
map(.,function(a){
a$anova
}) %>%
bind_rows(.,.id = "degron") %>%
mutate(Step = as.character(Step),
Step = ifelse(Step == "", "Full",Step)) %>%
group_by(degron) %>%
mutate(del.aic = AIC[1]-AIC) %>%
select(degron, Step, del.aic) %>%
split(.$degron) %>%
map(.,function(a){
a[nrow(a),] %>%
mutate(model = "reduced")
}) %>%
bind_rows(.id = "degron") %>%
mutate(degron = factor(degron, levels = c("GFP-mODC", "GFP-CLN2","yeGFP"))) %>%
ggplot(.,aes(x = del.aic, y = degron))+
geom_col(width = 0.2)+
theme(text = element_text(size = 8))+
# scale_x_log10()+
xlab(TeX("$Delta(AIC_{full} - AIC_{step})"))+
ylab("Regressor Dropped")+
theme_pubr()+
theme(text = element_text(size = 8))
#step AIC with only the fluorescent markers
#looking at which regressor contributes to the overall variability
full.stepAIC.fp %>%
map(., broom::tidy)
$`GFP-CLN2`
$`GFP-mODC`
$yeGFP
NA
Variance in t-half explained by each regressor using anova
var.explained
$yeGFP
$`yeGFP-CLN2`
$`yeGFP-mODC`
NA
#plotting the variance explained
remain.reg <- data.frame(sample = c("yeGFP-CLN2","yeGFP-CLN2","yeGFP","yeGFP"),
predictor = c("Rate of Maturation", "Shape","Shape","Pup1"),
var.exp = rep(0,4),
value.Pr..F. = rep(0,4))
var.exp.plt <- var.explained %>%
bind_rows() %>%
bind_rows(.,remain.reg) %>%
filter(predictor != "Residuals") %>%
dplyr::select(sample, predictor, var.exp,value.Pr..F.) %>%
mutate(sample = factor(sample , levels = c("yeGFP-mODC","yeGFP-CLN2","yeGFP"))) %>%
# mutate(var.pal = ifelse(value.Pr..F. < 0.05, "<0.05",">0.05")) %>%
arrange(sample) %>%
ggplot(.,aes(x = predictor, y = var.exp ))+
geom_col(width = 0.5)+
facet_wrap(~sample, scales = "free")+
scale_x_discrete(labels = function(x) str_wrap(x, width = 5))+
theme_pubr()+
theme(text = element_text(size = 8),
axis.line = element_line(size = 0.1),
strip.background = element_blank())+
ylim(0,20)+
ylab("Variance explained (%)")+
xlab("Cellular features")
var.exp.plt

#stepAIC with proteasome inhibition experiments With all fp
regressors
temp.df.list.dmso <- mlr.df %>%
filter(treatment != "none") %>%
split(.$treatment)
full.stepAIC.fp.dmso <- lapply(temp.df.list.dmso, function(a){
step(lm(t.half ~ ., data = a %>%
dplyr::select(regressors.fp,
t.half,
-dy,
-treatment)),
direction = "backward", trace = T)
})
lapply(full.stepAIC.fp.dmso, summary) %>% map(., broom::tidy) %>%
bind_rows(.id = "sample") %>%
split(.$sample)
lapply(full.stepAIC.fp.dmso, summary) %>% map(., broom::glance) %>%
bind_rows(.id = "sample") %>%
split(.$sample)
with fp regressors + celluar shape
mlr.df %>%
filter(treatment != "none") %>%
split(.$treatment)
$`1uM`
$`2.5uM`
$`50uM`
$`5uM`
$dmso1
$dmso2
NA
Variance in t-half explained by each regressor
full.stepAIC.dmso %>%
map(., anova %>% as.data.frame) %>%
bind_rows(.id = "sample") %>%
rownames_to_column(var = "predictor") %>%
# filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3")) %>%
group_by(sample) %>%
mutate(var.exp = (value.Sum.Sq/sum(value.Sum.Sq))*100) %>%
split(.$sample)
$`1uM`
$`2.5uM`
$`50uM`
$`5uM`
$dmso1
$dmso2
NA
#using regsubsets
library(leaps)
full.regSub.fp <- lapply(temp.df.list, function(a){
n <- nrow(a)
regsubsets(t.half ~ ., data = a %>%
dplyr::select(regressors.fp,
t.half,
-dy,
-treatment),
nvmax = NULL)
})
regSub.summary <- full.regSub.fp %>% map(.,summary)
lapply(regSub.summary, function(a){
data.frame(model = a$outmat,
cp = a$cp,
bic = a$bic)
}) %>% bind_rows(.id = "degron") %>%
group_by(degron) %>%
arrange(degron, cp)
full.regSub <- lapply(temp.df.list, function(a){
n <- nrow(a)
regsubsets(t.half ~ ., data = a %>%
dplyr::select(regressors,
t.half,
-dy,
-treatment),
nvmax = NULL)
})
regSub.summary2 <- full.regSub %>% map(.,summary)
lapply(regSub.summary2, function(a){
data.frame(model = a$outmat,
cp = a$cp,
bic = a$bic)
}) %>% bind_rows(.id = "degron") %>%
group_by(degron) %>%
arrange(degron, bic
) %>% split(.$degron)
#plots:
gfp.6.cor.plt <- mlr.df %>%
mutate(dm = log10(dm)) %>%
filter(degron %in% c("mODC.2", "cln2.3", "cln2.4", "stable.2", "stable.3")) %>%
dplyr::select(t.half,
regressors,
degron) %>%
rename(
"GFP" = "gfp.mean.bg.af.sub.new",
"Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
"DNA" = "dapi.sum.bg.sub.puncta",
"Area" = "area"
) %>%
pivot_longer(cols = 2:7) %>%
mutate(degron = case_when(
degron %in% c("cln2.3", "cln2.2", "cln2", "cln2.4") ~ "yeGFP-CLN2",
degron %in% c("mODC.2", "mODC") ~ "yeGFP-mODC",
degron %in% c("stable", "stable.2", "stable.3") ~ "yeGFP"
),
degron = factor(degron , levels = c("yeGFP-mODC", "yeGFP-CLN2", "yeGFP"))
) %>%
filter(!(name %in% c("shape","dm"))) %>%
ggplot(., aes(x = value, y = t.half)) +
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 2) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
facet_wrap(degron ~ name, scales = "free", ncol = 4) +
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none",
axis.line = element_line(size = 0.1))+
ylab("Half-life [min.]")+
xlab("A.U")
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(regressors)` instead of `regressors` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
Warning: Ignoring unknown parameters: guides
gfp.6.cor.plt
`geom_smooth()` using formula 'y ~ x'

mlr.df %>%
filter(degron %in% c("mODC.2", "cln2.3", "cln2.4", "stable.2", "stable.3")) %>%
dplyr::select(t.half,
regressors.fp,
degron) %>%
mutate(norm.rfp = rfp.mean.bg.sub.puncta/area)
Error in `mutate()`:
! Problem while computing `norm.rfp = rfp.mean.bg.sub.puncta/area`.
Caused by error in `rfp.mean.bg.sub.puncta / area`:
! non-numeric argument to binary operator
Backtrace:
1. ... %>% mutate(norm.rfp = rfp.mean.bg.sub.puncta / area)
3. dplyr:::mutate.data.frame(., norm.rfp = rfp.mean.bg.sub.puncta/area)
4. dplyr:::mutate_cols(.data, dplyr_quosures(...), caller_env = caller_env())
6. mask$eval_all_mutate(quo)
GFP intensity vs t-half cor plot
gfp.Int.cor.plt
`geom_smooth()` using formula 'y ~ x'

#patchwork for 3 cellular features and t-half
cellular.halfLife.plt <- (deltaR2.plt.all/gfp.3.cor.plt)+
plot_layout(guides = "collect", heights = c(0.3,0.7))+
plot_annotation(tag_levels = "A")
cellular.halfLife.plt
ggsave(plot = cellular.halfLife.plt, filename = "cellular_halfLife_cor.png", path = "~/plots/paper1/figures/fig_2/", width = 6.5, height = 8)
ggsave(plot = cellular.halfLife.plt, filename = "cellular_halfLife_cor.pdf", path = "~/plots/paper1/figures/fig_2/", width = 6.5, height = 8)
#patchwork for GFP intensity and t-half
gfpInt.halfLife.plt <- (deltaR2.plt.all/gfp.Int.cor.plt)+
plot_layout(guides = "collect")+
plot_annotation(tag_levels = "A")
gfpInt.halfLife.plt
`geom_smooth()` using formula 'y ~ x'

ggsave(plot = gfpInt.halfLife.plt, filename = "gfpInt_halfLife_cor.pdf", path = "~/plots/paper1/figures/fig_2/", width = 5.5, height = 6)
`geom_smooth()` using formula 'y ~ x'
#for GRC poster
ggsave(plot =gfp.Int.cor.plt , filename = "gfpInt_cor.pdf",path = "~/plots/paper1/figures/fig_2/", width =12, height = 3)
`geom_smooth()` using formula 'y ~ x'
with prottein inhibition
mlr.df %>%
mutate(dm = log10(dm)) %>%
filter(degron %in% c ("mODC") ) %>%
# filter(!(treatment %in% c("none", "dmso1","50uM")),
# ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>%
dplyr::select(t.half,
regressors,
degron,
treatment) %>%
rename(
"GFP" = "gfp.mean.bg.af.sub.new",
"Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
"DAPI" = "dapi.sum.bg.sub.puncta",
"Area" = "area"
) %>%
pivot_longer(cols = 2:7) %>%
mutate(degron = case_when(
degron %in% c("mODC") ~ "yeGFP-mODC"),
treatment = factor(treatment, levels = c("none","dmso1","dmso2","1uM","2.5uM","5uM","50uM"))) %>%
filter(!(name %in% c("shape","dm"))) %>%
ggplot(., aes(x = value, y = t.half)) +
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 2) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
facet_grid(treatment ~ name, scales = "free") +
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none")+
ylab("Half-Life [min.]")+
xlab("A.U")
Warning: Ignoring unknown parameters: guides
`geom_smooth()` using formula 'y ~ x'

mlr.df %>%
mutate(dm = log10(dm)) %>%
filter(degron %in% c ("mODC") ) %>%
filter(!(treatment %in% c("none", "dmso1","50uM")),
ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>%
dplyr::select(t.half,
regressors,
degron,
treatment) %>%
ggplot(.,aes(x = area, y = rfp.mean.bg.sub.puncta))+
geom_point()+
geom_smooth(method = "lm", se = F)+
facet_wrap(~treatment)+
stat_cor()
mlr.df %>%
filter(treatment == "none") %>%
ggplot(.,aes(x = dapi.sum.bg.sub.puncta))+
geom_histogram()+
facet_wrap(~degron, scales = "free")
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

#ggpairs
gfp.area.cor.ggPair
$`yeGFP-mODC`
plot: [1,1] [====>----------------------------------------------------------------------------------] 6% est: 0s
plot: [1,2] [==========>----------------------------------------------------------------------------] 12% est: 1s
plot: [1,3] [===============>-----------------------------------------------------------------------] 19% est: 1s
plot: [1,4] [=====================>-----------------------------------------------------------------] 25% est: 1s
plot: [2,1] [==========================>------------------------------------------------------------] 31% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [2,2] [================================>------------------------------------------------------] 38% est: 1s
plot: [2,3] [=====================================>-------------------------------------------------] 44% est: 1s
plot: [2,4] [===========================================>-------------------------------------------] 50% est: 1s
plot: [3,1] [================================================>--------------------------------------] 56% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [3,2] [=====================================================>---------------------------------] 62% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [3,3] [===========================================================>---------------------------] 69% est: 0s
plot: [3,4] [================================================================>----------------------] 75% est: 0s
plot: [4,1] [======================================================================>----------------] 81% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,2] [===========================================================================>-----------] 88% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,3] [=================================================================================>-----] 94% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,4] [=======================================================================================]100% est: 0s
$`yeGFP-CLN2`
plot: [1,1] [====>----------------------------------------------------------------------------------] 6% est: 0s
plot: [1,2] [==========>----------------------------------------------------------------------------] 12% est: 0s
plot: [1,3] [===============>-----------------------------------------------------------------------] 19% est: 1s
plot: [1,4] [=====================>-----------------------------------------------------------------] 25% est: 1s
plot: [2,1] [==========================>------------------------------------------------------------] 31% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [2,2] [================================>------------------------------------------------------] 38% est: 1s
plot: [2,3] [=====================================>-------------------------------------------------] 44% est: 1s
plot: [2,4] [===========================================>-------------------------------------------] 50% est: 1s
plot: [3,1] [================================================>--------------------------------------] 56% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [3,2] [=====================================================>---------------------------------] 62% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [3,3] [===========================================================>---------------------------] 69% est: 0s
plot: [3,4] [================================================================>----------------------] 75% est: 0s
plot: [4,1] [======================================================================>----------------] 81% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,2] [===========================================================================>-----------] 88% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,3] [=================================================================================>-----] 94% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,4] [=======================================================================================]100% est: 0s
$yeGFP
plot: [1,1] [====>----------------------------------------------------------------------------------] 6% est: 0s
plot: [1,2] [==========>----------------------------------------------------------------------------] 12% est: 0s
plot: [1,3] [===============>-----------------------------------------------------------------------] 19% est: 1s
plot: [1,4] [=====================>-----------------------------------------------------------------] 25% est: 1s
plot: [2,1] [==========================>------------------------------------------------------------] 31% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [2,2] [================================>------------------------------------------------------] 38% est: 1s
plot: [2,3] [=====================================>-------------------------------------------------] 44% est: 0s
plot: [2,4] [===========================================>-------------------------------------------] 50% est: 0s
plot: [3,1] [================================================>--------------------------------------] 56% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [3,2] [=====================================================>---------------------------------] 62% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [3,3] [===========================================================>---------------------------] 69% est: 0s
plot: [3,4] [================================================================>----------------------] 75% est: 0s
plot: [4,1] [======================================================================>----------------] 81% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,2] [===========================================================================>-----------] 88% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,3] [=================================================================================>-----] 94% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,4] [=======================================================================================]100% est: 0s



ggsave(plot = gfp.area.cor.ggPair$`yeGFP-mODC`, filename = "gfp_mODC_4Cor_ggP.png", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP-mODC`, filename = "gfp_mODC_4Cor_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP-CLN2`, filename = "gfp_cln2_4Cor_ggP.png", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP-CLN2`, filename = "gfp_cln2_4Cor_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP`, filename = "gfp_4Cor_ggP.png", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP`, filename = "gfp_4Cor_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
test.ggP <- (wrap_elements(ggmatrix_gtable(gfp.area.cor.ggPair$`yeGFP-mODC`))|wrap_elements(ggmatrix_gtable(gfp.area.cor.ggPair$`yeGFP-CLN2`))| wrap_elements(ggmatrix_gtable(gfp.area.cor.ggPair$yeGFP)))+
plot_annotation(tag_levels = "A")
ggsave(plot = test.ggP, filename = "test_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 6.5, height = 3)
#area vs pup1 vs dna vs gfp
df_corSup_fig <- mlr.df %>%
filter(degron %in% c("mODC.2", "cln2.3", "cln2.4", "stable.2", "stable.3")) %>%
dplyr::select(t.half,
regressors,
degron) %>%
rename(
"GFP" = "gfp.mean.bg.af.sub.new",
"Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
"DNA" = "dapi.sum.bg.sub.puncta",
"Area" = "area"
) %>%
dplyr::select(Area, DNA, `Pup1-tDimer`,GFP,degron ) %>%
mutate(
degron = case_when(
degron %in% c("cln2.3", "cln2.4") ~ "yeGFP-CLN2",
degron %in% c("mODC.2") ~ "yeGFP-mODC",
degron %in% c("stable.2", "stable.3") ~ "yeGFP"
),
degron = factor(degron , levels = c("yeGFP-mODC", "yeGFP-CLN2", "yeGFP"))
)
area.pup1 <- df_corSup_fig %>%
filter(degron == "yeGFP-mODC") %>%
ggplot(.,aes(x = Area, y = `Pup1-tDimer`))+
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 3) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none",
axis.line = element_line(size = 0.1))+
ylab("Pup1-tDimer [A.U]")+
xlab("Area [A.U]")
Warning: Ignoring unknown parameters: guides
dna.pup1 <- df_corSup_fig %>%
filter(degron == "yeGFP-mODC") %>%
ggplot(.,aes(x = DNA, y = `Pup1-tDimer`))+
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 3) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none",
axis.line = element_line(size = 0.1))+
ylab("Pup1-tDimer [A.U]")+
xlab("DNA [A.U]")
Warning: Ignoring unknown parameters: guides
dna.area <- df_corSup_fig %>%
filter(degron == "yeGFP-mODC") %>%
ggplot(.,aes(x = DNA, y = Area))+
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 3) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none",
axis.line = element_line(size = 0.1))+
ylab("Area [A.U]")+
xlab("DNA [A.U]")
Warning: Ignoring unknown parameters: guides
gfpInt.cor.plt <- df_corSup_fig %>%
pivot_longer(cols = 1:3) %>%
# filter(degron == "yeGFP-mODC") %>%
ggplot(.,aes(x = value, y = GFP))+
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 3) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
facet_wrap(degron~name, scales = "free")+
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none",
axis.line = element_line(size = 0.1))+
xlab("A.U")
Warning: Ignoring unknown parameters: guides
ggsave(plot = test_cor, filename = "area.pup1.dna.gfp_cor.pdf", path = "~/plots/paper1/figures/fig_2/", width = 6.5, height = 7)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
#Partial correlations ppcor
#partial correlations
ppCor.list <- mlr.df2 %>%
filter(treatment == "none") %>% split(.$degron) %>%
map(.,function(a){
a <- a %>%
dplyr::select(t.half, area, dapi.sum.bg.sub.puncta, rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>%
na.omit()
ppcor::pcor(a)
})
#correlations
cor.all <- mlr.df2 %>%
filter(treatment == "none") %>%
split(.$degron) %>%
map(.,function(a){
a <- a %>%
dplyr::select(t.half, area, dapi.sum.bg.sub.puncta,rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>%
na.omit()
cor(a)
})
ppCor.df <- ppCor.list %>%
map(.,function(a){
a$estimate %>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
dplyr::select(t.half, regressor) %>%
left_join(.,a$p.value%>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
rename("p.value" = "t.half") %>%
dplyr::select(p.value, regressor), by = "regressor")
}) %>%
bind_rows(.id = "degron")
single.core.df <- cor.all %>%
map(.,function(a){
a%>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
dplyr::select(t.half, regressor)
}) %>%
bind_rows(.id = "degron") %>%
rename("single.core"="t.half")
library(gtools)
ppCoor.fig <- ppCor.df %>%
left_join(.,single.core.df, by = c("degron","regressor")) %>%
rename("Partial-Pariwise"="t.half",
"Standard-Pariwise" = "single.core") %>%
pivot_longer(cols = c("Partial-Pariwise","Standard-Pariwise")) %>%
mutate(regressor = case_when(regressor == "gfp.mean.bg.af.sub.new" ~ "GFP" ,
regressor == "area" ~ "Area",
regressor == "rfp.mean.bg.sub.puncta" ~ "Pup1",
regressor == "dapi.sum.bg.sub.puncta" ~ "DNA" ,
regressor == "t.half" ~ "half-life"),
degron = factor(degron, levels = c("yeGFP-mODC","yeGFP-CLN2","yeGFP")),
name = factor(name , levels = c("Standard-Pariwise", "Partial-Pariwise")),
sig = stars.pval(p.value),
sig = ifelse(sig == " ", "NS", sig)) %>%
# filter(p.value < 0.05) %>%
filter(regressor != "half-life") %>%
ggplot(.,aes(x = regressor , y = value, fill = name))+
geom_col(width = 0.5, position = "dodge")+
facet_wrap(~degron)+
geom_hline(yintercept = 0, size = 0.1)+
scale_y_continuous(breaks = seq(-0.5,0.5, by = 0.1))+
theme_pubr()+
theme(text = element_text(size = 8),
legend.key.size = unit(4,"mm"),
legend.position = "top",
axis.line = element_line(size = 0.1),
strip.background = element_blank())+
scale_fill_manual(values = c("lightsteelblue4" ," steelblue4"), name = NULL)+
ylab("Correlation with Half-life ")+
xlab("Cellular features")
ppCoor.fig

#patchwork for 4 cellular features (area, gfp, dapi, pup1) and
t-half
(gfp.6.cor.plt/var.exp.plt/ppCoor.fig)
`geom_smooth()` using formula 'y ~ x'

ggsave(plot = gfp.4cor.hf.ppCor.plt, filename = "gfp_4cor_halfLife_ppcor.png", path = "~/plots/paper1/figures/fig_2/", width = 7, height = 9)
`geom_smooth()` using formula 'y ~ x'
ggsave(plot = gfp.4cor.hf.ppCor.plt, filename = "gfp_4cor_halfLife_ppcor.pdf", path = "~/plots/paper1/figures/fig_2/", width = 7, height = 9)
`geom_smooth()` using formula 'y ~ x'
#with protein inhibion
ppCor.PrtIn.list <- mlr.df %>%
filter(treatment != "none") %>%
filter(ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>%
split(.$treatment) %>%
map(.,function(a){
a <- a %>%
dplyr::select(t.half, area, dapi.sum.bg.sub.puncta, rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>%
na.omit()
ppcor::pcor(a)
})
cor.PrtIn.all <- mlr.df %>%
filter(treatment != "none") %>%
filter(ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>%
split(.$treatment) %>%
map(.,function(a){
a <- a %>%
dplyr::select(t.half, area, dapi.sum.bg.sub.puncta, rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>%
na.omit()
cor(a)
})
ppCor.PrtIn.df <- ppCor.PrtIn.list %>%
map(.,function(a){
a$estimate %>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
dplyr::select(t.half, regressor) %>%
left_join(.,a$p.value%>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
rename("p.value" = "t.half") %>%
dplyr::select(p.value, regressor), by = "regressor")
}) %>%
bind_rows(.id = "treatment")
single.core.Prtn.df <- cor.PrtIn.all %>%
map(.,function(a){
a%>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
dplyr::select(t.half, regressor)
}) %>%
bind_rows(.id = "treatment") %>%
rename("single.core"="t.half")
correlation of pup1 with mODC with treated with proteasome
inhibitors

#when you normalize pup1 with the area
mlr.df %>%
mutate(dm = log10(dm)) %>%
filter(degron %in% c("mODC.2", "cln2.3", "cln2.4", "stable.2", "stable.3")) %>%
dplyr::select(t.half,
regressors,
degron) %>%
rename(
"GFP" = "gfp.mean.bg.af.sub.new",
"Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
"DNA" = "dapi.sum.bg.sub.puncta",
"Area" = "area"
) %>%
mutate(norm.pup1 = `Pup1-tDimer`/Area) %>%
pivot_longer(cols = c(2:7,9)) %>%
mutate(degron = case_when(
degron %in% c("cln2.3", "cln2.2", "cln2", "cln2.4") ~ "yeGFP-CLN2",
degron %in% c("mODC.2", "mODC") ~ "yeGFP-mODC",
degron %in% c("stable", "stable.2", "stable.3") ~ "yeGFP"
),
degron = factor(degron , levels = c("yeGFP-mODC", "yeGFP-CLN2", "yeGFP"))
) %>%
filter(!(name %in% c("shape","dm"))) %>%
ggplot(., aes(x = value, y = t.half)) +
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 2) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
facet_wrap(degron ~ name, scales = "free", ncol = 4) +
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none")+
ylab("Half-Life [min.]")+
xlab("A.U")
LS0tCnRpdGxlOiAiQ29ycmVsYXRpb25zIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KEdHYWxseSkKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkobGF0ZXgyZXhwKQpsaWJyYXJ5KHBhdGNod29yaykKCmBgYAoKI2xvYWQgdGhlIGRhdGFmcmFtZXMgZm9yIHRoZSBmaWd1cmUKYGBge3J9CmFpYy5kZiA8LSByZWFkX2Nzdigifi9wbG90cy9hbGxfZGF0YS9haWMuY3N2IikKCmFpYy5kZiAlPiUgZmlsdGVyKHRyZWF0bWVudCA9PSAiNXVNIiwgbW9kZWwgPT0gImR5LmRtIikgJT4lIG11dGF0ZSh0LmhhbGYgPSBsb2coMikvZHkpICU+JSBmaWx0ZXIodC5oYWxmID4gMTMwKQoKYGBgCgoKcmVtb3ZlIGNlbGxzIGluIHRoZSBlZGdlcyA6CnBvcy54ID4gNDUgJiA8IDExNTAKcG9zLnkgPiA0NSAmIDwgMTAwMAojI2FkZCB0aGUgcmVwbGljYXRlIGluZm8gCmBgYHtyfQphaWMuZGYgPC0gYWljLmRmICU+JSAKICBtdXRhdGUoZXhwLmZpZWxkID0gcGFzdGUwKHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDJdLCJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDNdKSwKICAgIGNvbG9ueSA9IGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zMyIsICIyMG1pbl9zNCIpIH4gIlJlcGxpY2F0ZSAxIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNSIsICIyMG1pbl9zNiIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3M3IiwgIjIwbWluX3M4IiAsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIikpCgphaWMuZGYgPC0gYWljLmRmICU+JSAKICBtdXRhdGUoY29sb255ID0gaWZlbHNlKGRlZ3JvbiA9PSAic3RhYmxlIiAmIHJlZCA9PSAicHVwMS1yZnAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNCIsICIyMG1pbl9zNSIpIH4gIlJlcGxpY2F0ZSAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNiIsICIyMG1pbl9zNyIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zOCIsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIiksIGNvbG9ueSkpIAogIApgYGAKCiMjQ2VsbHVsYXIgYXR0cmlidXRlcwpgYGB7cn0KcHVwMS5jZWxsLmF0dHIgPC0gcmVhZF9jc3YoIn4vcGxvdHMvYWxsX2RhdGEvYWxsX3B1cDFfY2VsbF9hdHRyLmNzdiIpCmBgYAoKIyMjcHVwMS1SRlAgYmFja2dyb3VuZApgYGB7cn0KcHVwMS5jZWxsLmF0dHIgPC0gcHVwMS5jZWxsLmF0dHIgJT4lIAogIG11dGF0ZShleHAuZmllbGQgPSBwYXN0ZTAoc3RyX3NwbGl0KGNlbGwuaWQsICJfIiwgc2ltcGxpZnkgPSBUKVssMl0sIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3NwbGl0KGNlbGwuaWQsICJfIiwgc2ltcGxpZnkgPSBUKVssM10pLAogICAgY29sb255ID0gY2FzZV93aGVuKGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3MzIiwgIjIwbWluX3M0IikgfiAiUmVwbGljYXRlIDEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3M1IiwgIjIwbWluX3M2IikgfiAiUmVwbGljYXRlIDIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwLmZpZWxkICVpbiUgYygiMjBtaW5fczciLCAiMjBtaW5fczgiICwgIjIwbWluX3M5IikgfiAiUmVwbGljYXRlIDMiKSkKCnB1cDEuY2VsbC5hdHRyIDwtIHB1cDEuY2VsbC5hdHRyICU+JSAKICBtdXRhdGUoY29sb255ID0gaWZlbHNlKGRlZ3JvbiA9PSAic3RhYmxlIiAmIHJlZCA9PSAicHVwMS1yZnAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNCIsICIyMG1pbl9zNSIpIH4gIlJlcGxpY2F0ZSAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNiIsICIyMG1pbl9zNyIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zOCIsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIiksIGNvbG9ueSkpIAogIApgYGAKCmBgYHtyfQojcmVtb3ZpbmcgdGhlIDQwbWluIGFuZCA2MG1pbiBleHBlcmltZW50cyBmcm9tIHRoZSBzdGFibGUgZ2ZwIGV4cGVyaW1lbnRzCnB1cDEuY2VsbC5hdHRyIDwtIHB1cDEuY2VsbC5hdHRyICU+JQogIG11dGF0ZShleHAgPSBzdHJfc3BsaXQoZXhwLmZpZWxkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDFdKSAlPiUgCiAgZmlsdGVyKGV4cCA9PSAiMjBtaW4iKQpgYGAKCkFkZGluZyB0aGUgZ2ZwLnN1bSBjb2x1bW4gZm9yIHRoZSBzdGFibGUgR0ZQIGV4cGVyaW1lbnQKYGBge3J9CnB1cDEuY2VsbC5hdHRyIDwtIHJlYWRfY3N2KCJ+L3Bsb3RzL3B1cDEtcmZwLWdmcC1kZWNheS80LTI4LTIxLThockdGUC9kYXRhL2dmcF9zdGFibGVfZmlsdGVyZWQuY3N2IikgJT4lIAogIGZpbHRlcihpbWFnZS5ubyA9PSAxKSAlPiUgCiAgZHBseXI6OnNlbGVjdChjZWxsLmlkLCBnZnBTdW1CZ0FGc3ViKSAlPiUgCiAgbXV0YXRlKGNlbGwuaWQgPSBwYXN0ZTAoY2VsbC5pZCwiXyIsInN0YWJsZV9wdXAxLXJmcF9ub25lIikpICU+JSAKICBkcGx5cjo6cmVuYW1lKCJnZnAuc3VtLmJnLmFmLnN1YiIgPSAiZ2ZwU3VtQmdBRnN1YiIpICU+JSAKICBsZWZ0X2pvaW4ocHVwMS5jZWxsLmF0dHIgJT4lIAogICAgICAgICAgICAgIGZpbHRlcihkZWdyb24gPT0gInN0YWJsZSIpICU+JSAKICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KC1nZnAuc3VtLmJnLmFmLnN1YiksLiwgYnkgPSAiY2VsbC5pZCIpICU+JSAKICBiaW5kX3Jvd3MocHVwMS5jZWxsLmF0dHIgJT4lIAogICAgICAgICAgICAgIGZpbHRlcihkZWdyb24gIT0gInN0YWJsZSIpLC4pCmBgYAoKcmVtb3ZpbmcgbXVsdGlwbGUgZW50cmllcyBvZiB0aGUgY2VsbCBiZWNhdXNlIHNvbWUgY2VsbCBoYXZlIG1vcmUgdGhhbiAKYGBge3J9Cm11bHRpcGxlLnB1cDEgPC0gcHVwMS5jZWxsLmF0dHIgJT4lIAogIG11dGF0ZShkYXBpLm1lYW4uYmcuc3ViLnB1bmN0YSA9IGlmZWxzZShpcy5uYShkYXBpLm1lYW4uYmcuc3ViLnB1bmN0YSksIDAsIGRhcGkubWVhbi5iZy5zdWIucHVuY3RhKSAsIAogICAgICAgICByZnAubWVhbi5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGlzLm5hKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEpLCAwICwgcmZwLm1lYW4uYmcuc3ViLnB1bmN0YSkpICU+JSAKICBmaWx0ZXIocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSA+IDApICU+JSAKICBncm91cF9ieShjZWxsLmlkKSAlPiUgCiAgdGFsbHkoKSAlPiUgCiAgZmlsdGVyKG4+MSkKCnB1cDEuY2VsbC5hdHRyPC0gcHVwMS5jZWxsLmF0dHIgJT4lIAogIGdyb3VwX2J5KGNlbGwuaWQpICU+JSAKICBtdXRhdGUocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSA9IGlmZWxzZShjZWxsLmlkICVpbiUgbXVsdGlwbGUucHVwMSRjZWxsLmlkICwgbWVhbihyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgcmZwLm1lYW4uYmcuc3ViLnB1bmN0YSksCiAgICAgICAgIHJmcC5zdW0uYmcuc3ViLnB1bmN0YSA9IGlmZWxzZShjZWxsLmlkICVpbiUgbXVsdGlwbGUucHVwMSRjZWxsLmlkLCBzdW0ocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSksIHJmcC5zdW0uYmcuc3ViLnB1bmN0YSkpICU+JSAKICAgIGRpc3RpbmN0KGNlbGwuaWQsIC5rZWVwX2FsbCA9IFRSVUUpIAogIApgYGAKCgojcHJvdGVhc29tZSBpbmhpYml0aW9uIGV4cGVyaW1lbnRzCmBgYHtyfQpwcm90SW5oaS5hdHRyIDwtIHJlYWRfY3N2KCJ+L3Bsb3RzL2FsbF9kYXRhL2FsbF9tZzEzNV9hdHRyLmNzdiIpICU+JSAKICByZW5hbWUoImNlbGwuaWQiID0gInVuaXF1ZS50cmFja0lEIikgJT4lIAogIGZpbHRlcih0aW1lcG9pbnQgPT0gMSkgJT4lIAogIG11dGF0ZShjZWxsLmlkID0gcGFzdGUwKGNlbGwuaWQgLCJfIixkZWdyb24sIl8iLHJlZCwiXyIsdHJlYXRtZW50KSkgJT4lIAogIG11dGF0ZShleHAuZmllbGQgPSBwYXN0ZTAoc3RyX3NwbGl0KGNlbGwuaWQsICJfIiwgc2ltcGxpZnkgPSBUKVssMl0sIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3NwbGl0KGNlbGwuaWQsICJfIiwgc2ltcGxpZnkgPSBUKVssM10pLAogICAgY29sb255ID0gY2FzZV93aGVuKGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3MzIiwgIjIwbWluX3M0IikgfiAiUmVwbGljYXRlIDEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3M1IiwgIjIwbWluX3M2IikgfiAiUmVwbGljYXRlIDIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwLmZpZWxkICVpbiUgYygiMjBtaW5fczciLCAiMjBtaW5fczgiICwgIjIwbWluX3M5IikgfiAiUmVwbGljYXRlIDMiKSkKCm11bHRpcGxlLnByb0luaCA8LSBwcm90SW5oaS5hdHRyICU+JSAKICBtdXRhdGUoZGFwaS5tZWFuLmJnLnN1Yi5wdW5jdGEgPSBpZmVsc2UoaXMubmEoZGFwaS5tZWFuLmJnLnN1Yi5wdW5jdGEpLCAwLCBkYXBpLm1lYW4uYmcuc3ViLnB1bmN0YSkgLCAKICAgICAgICAgcmZwLm1lYW4uYmcuc3ViLnB1bmN0YSA9IGlmZWxzZShpcy5uYShyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgMCAsIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEpKSAlPiUgCiAgZmlsdGVyKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEgPiAwKSAlPiUgCiAgZ3JvdXBfYnkoY2VsbC5pZCkgJT4lIAogIHRhbGx5KCkgJT4lIAogIGZpbHRlcihuPjEpCgpwcm90SW5oaS5hdHRyIDwtIHByb3RJbmhpLmF0dHIgJT4lIAogIGdyb3VwX2J5KGNlbGwuaWQpICU+JSAKICBtdXRhdGUocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSA9IGlmZWxzZShjZWxsLmlkICVpbiUgbXVsdGlwbGUucHJvSW5oJGNlbGwuaWQgLCBtZWFuKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEpLCByZnAubWVhbi5iZy5zdWIucHVuY3RhKSwKICAgICAgICAgcmZwLnN1bS5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGNlbGwuaWQgJWluJSBtdWx0aXBsZS5wcm9JbmgkY2VsbC5pZCwgc3VtKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEpLCByZnAuc3VtLmJnLnN1Yi5wdW5jdGEpKSAlPiUgCiAgICBkaXN0aW5jdChjZWxsLmlkLCAua2VlcF9hbGwgPSBUUlVFKSAgCiAgCgpgYGAKQWRkaW5nIHRoZSBwcm90ZWluIGluaGliaXRpb24gZXhwZXJpbWVudCBkYXRhCmBgYHtyfQpwdXAxLnByb0luaGkuYXR0ciA8LSBwdXAxLmNlbGwuYXR0ciAlPiUgCiAgYmluZF9yb3dzKC4scHJvdEluaGkuYXR0ciAlPiUgCiAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdCgtdGltZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtdGltZXBvaW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLWltYWdlLm5vLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC1sbi5nZnAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLWxuLmdmcC5kaWYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtdHJhY2tJRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC1nZnAuaW50ZW5zaXR5LmNlbnRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC1nZnAuaW50Lm1lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLmludC5tZWRpYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1nZnAuaW50LnN1bSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLW5vLm9mLnRyaWFuZ2xlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgLWZpZWxkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdGltZS5kaWYuZ2ZwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtcmVhbC50aW1lLmdmcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLXNhbXBsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLWF2Zy5nZnAuYmcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1NaW5fZ2ZwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLm1lYW4uYmcuc3ViLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC10ODAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC10OTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC10aHJlc2hvbGQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC10aHJlc2hvbGRfOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1nZnAubWVhbi5iZy5hZi5zdWIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC10aHJlc2hvbGRfODAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1NZWFuX2dmcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLWltYWdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtZXhwZXJpbWVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLWdmcC5zdW0uYmcuc3ViKSkKYGBgCgoKI2tlZXBpbmcgdGhlIGR5LmRtIG1vZGVsIHBhcmFtZXRlcnMgCmBgYHtyfQojb25seSBkeS5kbQpkeS5wdXAxLnJlcDEubWF0IDwtIGFpYy5kZiAlPiUgCiAgZmlsdGVyKHJlZCA9PSAicHVwMS1yZnAiKSAlPiUgCiAgZmlsdGVyKGlmZWxzZShkZWdyb24gJWluJSBjKCJzdGFibGUiLCJzdGFibGUuMiIsInN0YWJsZS4zIiksIGR5IDwgMC4xLCBkeSA8IDAuNSkpICU+JSAKICBncm91cF9ieShjZWxsLmlkKSAlPiUgCiAgZmlsdGVyKG1vZGVsID09ICJkeS5kbSIpICU+JSAKICBtdXRhdGUoZG0gPSBpZmVsc2UoaXMubmEoZG0pLCBJbmYsIGRtKSkgJT4lCiAgZmlsdGVyKCBkbSA+IDAuMDAwMDE1KQpgYGAKCiNjb3VudCB0aGUgbnVtYmVyIG9mIGNlbGxzIGluIGVhY2ggZXhwZXJpbWVudCAKYGBge3J9CmR5LnB1cDEucmVwMS5tYXQgJT4lIGdyb3VwX2J5KGRlZ3JvbiwgdHJlYXRtZW50KSAlPiUgdGFsbHkoKQpgYGAKI2NyZWF0aW5nIHRoZSBkZiBmb3IgdGhlIE1MUgpgYGB7cn0KbWxyLmRmIDwtIGR5LnB1cDEucmVwMS5tYXQgJT4lIAogICNsZWZ0IGpvaW4gd2l0aCB0aGUgZGYgd2l0aCBjZWxsdWxhciBhdHRyaWJ1dGVzCiAgbGVmdF9qb2luKC4scHVwMS5wcm9JbmhpLmF0dHIsIGJ5ID0gYygiY2VsbC5pZCIsInJlZCIsInRyZWF0bWVudCIsImRlZ3JvbiIsICJleHAuZmllbGQiLCJjb2xvbnkiKSkgJT4lIAogICNyZW1vdmUgY2VsbHMgd2l0aCBubyByZnAgcHVuY3RhIGluZm8gCiAgbXV0YXRlKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEgPSBpZmVsc2UoaXMubmEocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSksIDAsIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEpKSAlPiUgCiAgZmlsdGVyKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEgPiAwKQpgYGAKCiNjaGVja2luZyBob3cgbWFueSBjZWxscyB0aGVyZSBhcmUgaW4gZWFjaCBleHBlcmltZW50IApgYGB7cn0KbWxyLmRmICU+JSBncm91cF9ieShkZWdyb24sIHRyZWF0bWVudCkgJT4lIHRhbGx5KCkKYGBgCiNsb29raW5nIHRoZSBwbGFjZW1lbnQgb2Ygc2luZ2xlIGNlbGxzIGluIGltYWdlcwpgYGB7cn0KbWxyLmRmICU+JSAKICBmaWx0ZXIoKQogIGdncGxvdCguLGFlcyh4ID0gcG9zLngsIHkgPSBwb3MueSkpKwogIGdlb21fcG9pbnQoKSsKICBmYWNldF93cmFwKH5kZWdyb24pCmBgYAojI1JlbW92aW5nIHRoZSBjb2x1bW5zIHRoYXQgSSB3b250IHJlZ3Jlc3MgdXBvbgpgYGB7cn0KbWxyLmRmIDwtIG1sci5kZiAlPiUgCiAgZmlsdGVyKHBvcy54ID4gNDUgJiBwb3MueCA8IDExNTAsCiAgcG9zLnkgPiA0NSAmIHBvcy55IDwgMTAwMCkgJT4lCiAgZHBseXI6OnNlbGVjdCgtZiwgCiAgICAgICAgIC1yZnAubWVhbi5hZi5zdWIucHVuY3RhLAogICAgICAgICAtcmZwLnN1bS5hZi5zdWIucHVuY3RhLCAKICAgICAgICAgLWRhcGkuc3VtLmFmLnN1Yi5wdW5jdGEsCiAgICAgICAgIC1kYXBpLm1lYW4uYWYuc3ViLnB1bmN0YSwKICAgICAgICAgLW1vZGVsLCAKICAgICAgICAgLWssCiAgICAgICAgIC1mZXZhbHMsCiAgICAgICAgIC1nZXZhbHMsIAogICAgICAgICAtbml0ZXIsIAogICAgICAgICAtY29udmNvZGUsIAogICAgICAgICAta2t0MSwKICAgICAgICAgLWtrdDIsCiAgICAgICAgIC12YWx1ZSwKICAgICAgICAgLXh0aW1lLCAKICAgICAgICAgIyAtdHJlYXRtZW50LAogICAgICAgICAtcmZwLm1lYW4uYmcuc3ViLAogICAgICAgICAtcmZwLnN1bS5iZy5zdWIsCiAgICAgICAgIC1kYXBpLm1lYW4uYmcuc3ViLAogICAgICAgICAtZGFwaS5zdW0uYmcuc3ViLAogICAgICAgICAtZGFwaS5tZWFuLmJnLnN1Yi5wdW5jdGEsCiAgICAgICAgIC1hcmVhLnB1bmN0YSwKICAgICAgICAgLUJCX0IsCiAgICAgICAgIC1CQl9DLAogICAgICAgICAtcG9zLngsCiAgICAgICAgIC1wb3MueSwKICAgICAgICAgLWdmcC5zdW0uYmcuYWYuc3ViLAogICAgICAgICAtcmZwLnN1bS5iZy5zdWIucHVuY3RhLAogICAgICAgICAtbm8ub2Yudm94ZWxzLAogICAgICAgICAtdm9sdW1lLAogICAgICAgICAtc3BoZXJhY2l0eSkgJT4lIAogIG11dGF0ZShzaGFwZSA9IEVsaXBfQi9FbGlwX0MsIAogICAgICAgICB0LmhhbGYgPSBsb2coMikvZHkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1jZWxsLmlkLCAKICAgICAgICAgICAgICAgIC1yZWQsCiAgICAgICAgICAgICAgICAtZXhwLmZpZWxkLCAKICAgICAgICAgICAgICAgIC1haWMsCiAgICAgICAgICAgICAgICAtRWxpcF9CLAogICAgICAgICAgICAgICAgLUVsaXBfQywgCiAgICAgICAgICAgICAgICAtZXhwKSAKYGBgCgojUmVncmVzc29ycyB0byB1c2UgZm9yIE1MUgpgYGB7cn0KcmVncmVzc29ycyA8LSBjKCJkbSIsCiAgICAgICAgICAgICAgICAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIsCiAgICAgICAgICAgICAgICAjICJnZnAuc3VtLmJnLmFmLnN1YiIsCiAgICAgICAgICAgICAgICAiYXJlYSIsCiAgICAgICAgICAgICAgICAjICJuby5vZi52b3hlbHMiLAogICAgICAgICAgICAgICAgIyAic3BoZXJhY2l0eSIsCiAgICAgICAgICAgICAgICAjICJ2b2x1bWUiLAogICAgICAgICAgICAgICAgInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiLAogICAgICAgICAgICAgICAgIyAicmZwLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICAgICAgICAgICAgICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICAgICAgICAgICAgICJzaGFwZSIpCmBgYAoKRnVuY3Rpb24gdG8gZXZhbHVhdGUgc3RlcCBSIApgYGB7cn0Kc3RlcFIuZm4gPC0gZnVuY3Rpb24ocmVnLCBkZiwgcHJ0LmluaC50cnQsIGlkLnZhcikgewogICNnZXQgdGhlIGVzdGltYXRlcwogIHN0ZXBSLmVzdCA8LQogICAgbGFwcGx5KHJlZywgZnVuY3Rpb24oYSkgewogICAgICAjcmVncmVzc29ycyB0byByZW1vdmUgb25lIGJ5IG9uZQogICAgICB0ZW1wLmRmMiA8LSBkZiAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KGFsbF9vZihyZWcpLCAKICAgICAgICAgICAgICAgICAgICAgIGRlZ3JvbiwKICAgICAgICAgICAgICAgICAgICAgIHQuaGFsZiwKICAgICAgICAgICAgICAgICAgICAgICMgZHksIAogICAgICAgICAgICAgICAgICAgICAgY29sb255LCAKICAgICAgICAgICAgICAgICAgICAgIHRyZWF0bWVudCkgJT4lICNyZW1vdmVkIHQuaGFsZiBhbmQgcmVwbGFjZWQgd2l0aCBkeQogICAgICAgIHVuZ3JvdXAoKSAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KC1hKQogICAgICAKICAgICAgdGVtcC5kZjIgJT4lCiAgICAgICAgZmlsdGVyKHRyZWF0bWVudCAlaW4lIHBydC5pbmgudHJ0KSAlPiUKICAgICAgICBzcGxpdCguW2lkLnZhcl0pICU+JQogICAgICAgIG1hcCguLCBmdW5jdGlvbihiKSB7CiAgICAgICAgICBsbSh0LmhhbGYgfiAuLAogICAgICAgICAgICAgZGF0YSA9IGIgJT4lIGRwbHlyOjpzZWxlY3QoLWRlZ3JvbiwgLWNvbG9ueSwgLXRyZWF0bWVudCkpICU+JQogICAgICAgICAgICBicm9vbTo6dGlkeSgpCiAgICAgICAgfSkgJT4lCiAgICAgICAgYmluZF9yb3dzKC5pZCA9IGlkLnZhcikgJT4lCiAgICAgICAgbXV0YXRlKHJlbW92ZWQuY29sID0gYSkKICAgICAgCiAgICB9KSAlPiUKICAgIGJpbmRfcm93cygpCiAgCiAgI2dldCB0aGUgc3RhdHMgb2YgdGhlIG1vZGVsCiAgc3RlcFIuZ2xhbmNlIDwtIGxhcHBseShyZWcsIGZ1bmN0aW9uKGEpIHsKICAgIHRlbXAuZGYyIDwtIGRmICU+JQogICAgICBkcGx5cjo6c2VsZWN0KGFsbF9vZihyZWcpLCBkZWdyb24sIHQuaGFsZiwKICAgICAgICAgICAgICAgICAgICAjIGR5LCAKICAgICAgICAgICAgICAgICAgICBjb2xvbnksIHRyZWF0bWVudCkgJT4lICNyZW1vdmVkIHQuaGFsZiBhbmQgcmVwbGFjZWQgd2l0aCBkeQogICAgICBkcGx5cjo6c2VsZWN0KC1hKQogICAgCiAgICB0ZW1wLmRmMiAlPiUKICAgICAgZmlsdGVyKHRyZWF0bWVudCAlaW4lIHBydC5pbmgudHJ0KSAlPiUKICAgICAgc3BsaXQoLltpZC52YXJdKSAlPiUKICAgICAgbWFwKC4sIGZ1bmN0aW9uKGIpIHsKICAgICAgICBsbSh0LmhhbGYgfiAuLAogICAgICAgICAgIGRhdGEgPSBiICU+JSBkcGx5cjo6c2VsZWN0KC1kZWdyb24sLWNvbG9ueSwtdHJlYXRtZW50KSkgJT4lCiAgICAgICAgICBicm9vbTo6Z2xhbmNlKCkKICAgICAgfSkgJT4lCiAgICAgIGJpbmRfcm93cyguaWQgPSBpZC52YXIpICU+JQogICAgICBtdXRhdGUocmVtb3ZlZC5jb2wgPSBhKQogICAgCiAgfSkgJT4lCiAgICBiaW5kX3Jvd3MoKQogIAogICNnZXQgdGhlIGZpdHMKICBzdGVwUi5maXQgPC0gbGFwcGx5KHJlZywgZnVuY3Rpb24oYSkgewogICAgdGVtcC5kZjIgPC0gZGYgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoYWxsX29mKHJlZyksIGRlZ3JvbiwgdC5oYWxmLAogICAgICAgICAgICAgICAgICAgICMgZHksIAogICAgICAgICAgICAgICAgICAgIGNvbG9ueSwgdHJlYXRtZW50KSAlPiUgI3JlbW92ZWQgdC5oYWxmIGFuZCByZXBsYWNlZCB3aXRoIGR5CiAgICAgIGRwbHlyOjpzZWxlY3QoLWEpCiAgICAKICAgIHRlbXAuZGYyICU+JQogICAgICBmaWx0ZXIodHJlYXRtZW50ICVpbiUgcHJ0LmluaC50cnQpICU+JQogICAgICBzcGxpdCguW2lkLnZhcl0pICU+JQogICAgICBtYXAoLiwgZnVuY3Rpb24oYikgewogICAgICAgIGxtKHQuaGFsZiB+IC4sCiAgICAgICAgICAgZGF0YSA9IGIgJT4lIGRwbHlyOjpzZWxlY3QoLWRlZ3JvbiwgLWNvbG9ueSwtdHJlYXRtZW50KSkKICAgICAgfSkKICB9KQogIAogICNvdXRwdXQKICBzdGVwUi5saXN0IDwtIGxpc3Qoc3RlcFIuZXN0LAogICAgICAgICAgICAgICAgICAgICBzdGVwUi5nbGFuY2UsCiAgICAgICAgICAgICAgICAgICAgIHN0ZXBSLmZpdCkKICAKICBuYW1lcyhzdGVwUi5saXN0KSA8LSBjKCJzdGVwUi5lc3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgInN0ZXBSLmdsYW5jZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAic3RlcFIuZml0IikKICByZXR1cm4oc3RlcFIubGlzdCkKfQpgYGAKCmZ1bmN0aW9uIHRvIGV2YWx1YXRlIHRoZSBmdWxsIG1vZGVsCmBgYHtyfQpmdWxsTUxSLmZuIDwtIGZ1bmN0aW9uKHJlZ3Jlc3NvcnMsIGRmLCBwcnQuaW5oLnRydCwgaWQudmFyKSB7CiAgI3N0YXRpc3RpY3MKICBmdWxsUi5nbGFuY2UgPC0gZGYgJT4lCiAgICB1bmdyb3VwKCkgJT4lCiAgICBmaWx0ZXIodHJlYXRtZW50ICVpbiUgcHJ0LmluaC50cnQpICU+JQogICAgZHBseXI6OnNlbGVjdChhbGxfb2YocmVncmVzc29ycyksIAogICAgICAgICAgICAgICAgICBkZWdyb24sIAogICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICMgZHksIAogICAgICAgICAgICAgICAgICBjb2xvbnksIAogICAgICAgICAgICAgICAgICB0cmVhdG1lbnQpICU+JSAjcmVtb3ZlZCB0LmhhbGYgYW5kIHJlcGxhY2VkIHdpdGggZHkKICAgIHNwbGl0KC5baWQudmFyXSkgJT4lCiAgICBtYXAoLiwgZnVuY3Rpb24oYikgewogICAgICBsbSh0LmhhbGYgfiAuLAogICAgICAgICBkYXRhID0gYiAlPiUgZHBseXI6OnNlbGVjdCgtZGVncm9uLCAtY29sb255LCAtdHJlYXRtZW50KSkgJT4lCiAgICAgICAgYnJvb206OmdsYW5jZSgpCiAgICB9KSAlPiUKICAgIGJpbmRfcm93cyguaWQgPSBpZC52YXIpICU+JQogICAgbXV0YXRlKHJlbW92ZWQuY29sID0gIm5vbmUiKQogIAogICNlc3RpbWF0ZXMKICBmdWxsUi5lc3QgPC0gZGYgJT4lCiAgICB1bmdyb3VwKCkgJT4lCiAgICBmaWx0ZXIodHJlYXRtZW50ICVpbiUgcHJ0LmluaC50cnQpICU+JQogICAgZHBseXI6OnNlbGVjdChhbGxfb2YocmVncmVzc29ycyksIAogICAgICAgICAgICAgICAgICBkZWdyb24sCiAgICAgICAgICAgICAgICAgIHQuaGFsZiwKICAgICAgICAgICAgICAgICAgIyBkeSwgCiAgICAgICAgICAgICAgICAgIGNvbG9ueSwgCiAgICAgICAgICAgICAgICAgIHRyZWF0bWVudCkgJT4lICNyZW1vdmVkIHQuaGFsZiBhbmQgcmVwbGFjZWQgd2l0aCBkeQogICAgc3BsaXQoLltpZC52YXJdKSAlPiUKICAgIG1hcCguLCBmdW5jdGlvbihiKSB7CiAgICAgIGxtKHQuaGFsZiB+IC4sCiAgICAgICAgIGRhdGEgPSBiICU+JSBkcGx5cjo6c2VsZWN0KC1kZWdyb24sIC1jb2xvbnksLXRyZWF0bWVudCkpICU+JQogICAgICAgIGJyb29tOjp0aWR5KCkKICAgIH0pICU+JQogICAgYmluZF9yb3dzKC5pZCA9IGlkLnZhcikgJT4lCiAgICBtdXRhdGUocmVtb3ZlZC5jb2wgPSAibm9uZSIpCiAgCiAgI2ZpdHMKICBmdWxsTUxSLmZpdCA8LSBkZiAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIGZpbHRlcih0cmVhdG1lbnQgJWluJSBwcnQuaW5oLnRydCkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KGFsbF9vZihyZWdyZXNzb3JzKSwgCiAgICAgICAgICAgICAgICAgIGRlZ3JvbiwgCiAgICAgICAgICAgICAgICAgIHQuaGFsZiwKICAgICAgICAgICAgICAgICAgIyBkeSwgCiAgICAgICAgICAgICAgICAgIGNvbG9ueSwgCiAgICAgICAgICAgICAgICAgIHRyZWF0bWVudCkgJT4lICNyZW1vdmVkIHQuaGFsZiBhbmQgcmVwbGFjZWQgd2l0aCBkeQogICAgc3BsaXQoLltpZC52YXJdKSAlPiUKICAgIG1hcCguLCBmdW5jdGlvbihiKSB7CiAgICAgIGxtKHQuaGFsZiB+IC4sCiAgICAgICAgIGRhdGEgPSBiICU+JSBkcGx5cjo6c2VsZWN0KC1kZWdyb24sIC1jb2xvbnksIC10cmVhdG1lbnQpKQogICAgfSkKICAKICAjb3V0cHV0CiAgZnVsbE1MUi5saXN0IDwtIGxpc3QoZnVsbFIuZ2xhbmNlLAogICAgICAgICAgICAgICAgICAgICAgIGZ1bGxSLmVzdCwKICAgICAgICAgICAgICAgICAgICAgICBmdWxsTUxSLmZpdCkKICAKICBuYW1lcyhmdWxsTUxSLmxpc3QpIDwtIGMoImZ1bGxSLmdsYW5jZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJmdWxsUi5lc3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiZnVsbE1MUi5maXQiKQogIHJldHVybihmdWxsTUxSLmxpc3QpCn0KYGBgCgojZGYgd2hlcmUgdGhlIHR3byBleHBlcmltZW50cyBvZiBjbG4yIGFuZCBzdGFibGUtR0ZQIGFyZSBjbHViYmVkIApgYGB7cn0KbWxyLmRmMiA8LSBtbHIuZGYgJT4lIAogIGZpbHRlcihkZWdyb24gJWluJSBjKCJjbG4yLjMiLCJtT0RDLjIiLCJzdGFibGUuMyIsInN0YWJsZS4yIiwiY2xuMi40IikpICU+JSAKICBtdXRhdGUoZGVncm9uID0gY2FzZV93aGVuKGRlZ3JvbiAlaW4lIGMoImNsbjIuMyIsImNsbjIuMiIsImNsbjIiLCJjbG4yLjQiKSB+ICJ5ZUdGUC1DTE4yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIsICJtT0RDIikgIH4gInllR0ZQLW1PREMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlIiwic3RhYmxlLjIiLCJzdGFibGUuMyIpIH4gInllR0ZQIikpIAogIApgYGAKCnN0ZXAgTUxSIGVzdGltYXRlcyAKI3dpdGhvdXQgdGhlIHByb3RlaW4gaW5oaWJpdGlvbgpgYGB7cn0Kc3RlcFIubGlzdCA8LSBzdGVwUi5mbihyZWcgPSByZWdyZXNzb3JzLCAKICAgICAgICAgZGYgPSBtbHIuZGYyLAogICAgICAgICBwcnQuaW5oLnRydCA9ICJub25lIiwKICAgICAgICBpZC52YXIgPSAiZGVncm9uIikKCmZ1bGxSLmxpc3QgPC0gZnVsbE1MUi5mbihyZWcgPSByZWdyZXNzb3JzLAogICAgICAgICAgICAgICAgICAgICAgICAgZGYgPSBtbHIuZGYyLAogICAgICAgICAgICAgICAgICAgICAgICAgcHJ0LmluaC50cnQgPSAibm9uZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICBpZC52YXIgPSAiZGVncm9uIikKYGBgCgoKIzJEIGNvcnJlbGF0aW9uIHBsb3RzCmBgYHtyfQpsYXBwbHkocmVncmVzc29yc1sxXSwgZnVuY3Rpb24oYSl7CiAgbWxyLmRmICU+JSAKICAgIGZpbHRlcih0cmVhdG1lbnQgIT0gIm5vbmUiKSAlPiUgCiAgbXV0YXRlKHQuaGFsZiA9IGxvZygyKS9keSkgJT4lCiAgICAjIGZpbHRlcihkZWdyb24gJWluJSBjKCJzdGFibGUuMiIsInN0YWJsZS4zIikpICU+JSAKICAgICMgZmlsdGVyKCEoZGVncm9uICVpbiUgYygibU9EQyIsImNsbjIuMiIsImNsbjIiLCJzdGFibGUiKSkpICU+JSAKICAgICMgZmlsdGVyKHRyZWF0bWVudCAlaW4lIGMoImRtc28xIiwiZG1zbzIiKSkgJT4lICAlPiUgCiAgICAgIGdncGxvdCguLGFlcyh5ID0gdC5oYWxmLCB4ID0gLltbYV1dKSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICBzdGF0X2NvcigpKwogICAgIyBzdGF0X3JlZ2xpbmVfZXF1YXRpb24oKSsKICAgIGZhY2V0X3dyYXAofnRyZWF0bWVudCAsIHNjYWxlcyA9ICJmcmVlIikrCiAgICBsYWJzKHRpdGxlID0gYSkrCiAgICBzY2FsZV94X2xvZzEwKCkKICAKfSkKCmBgYAoKI3l+eCArIGMgc2luZ2xlIHZhcmlhYmxlIHJlZ3Jlc3Npb24Kc2luZ2xlIHJlZ3Jlc3NvciBzdGF0aXN0aWNzCmBgYHtyfQpzdGVwUi4xdmFyIDwtIGxhcHBseShyZWdyZXNzb3JzLCBmdW5jdGlvbihhKXsKICB0ZW1wLmRmMiA8LSBtbHIuZGYgJT4lIAogICAgdW5ncm91cCgpICU+JSAKICAgIGRwbHlyOjpzZWxlY3QoYSwgdC5oYWxmLGRlZ3JvbikKICAKICB0ZW1wLmRmMiAlPiUgCiAgICBzcGxpdCguJGRlZ3JvbikgJT4lIAogICAgbWFwKC4sZnVuY3Rpb24oYil7CiAgICAgIGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBiICU+JSBkcGx5cjo6c2VsZWN0KC1kZWdyb24pKSAlPiUgCiAgICAgICAgYnJvb206OmdsYW5jZSgpCiAgICB9KSAlPiUgCiAgICBiaW5kX3Jvd3MoLmlkID0gImRlZ3JvbiIpICU+JSAKICAgIG11dGF0ZShzaW5nbGUuY29sID0gYSkKICAgCn0pICU+JSAKICBiaW5kX3Jvd3MoKQpgYGAKCnNpbmdsZSByZWdyZXNzb3IgZXN0aW1hdGVzIApgYGB7cn0Kc3RlcFIuMXZhci5lc3QgPC0gbGFwcGx5KHJlZ3Jlc3NvcnMsIGZ1bmN0aW9uKGEpewogIHRlbXAuZGYyIDwtIHRlbXAuZGYgJT4lIAogICAgdW5ncm91cCgpICU+JSAKICAgIGRwbHlyOjpzZWxlY3QoYSwgdC5oYWxmLGRlZ3JvbikKICAKICB0ZW1wLmRmMiAlPiUgCiAgICBzcGxpdCguJGRlZ3JvbikgJT4lIAogICAgbWFwKC4sZnVuY3Rpb24oYil7CiAgICAgIGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBiICU+JSBkcGx5cjo6c2VsZWN0KC1kZWdyb24pKSAlPiUgCiAgICAgICAgYnJvb206OnRpZHkoKQogICAgfSkgJT4lIAogICAgYmluZF9yb3dzKC5pZCA9ICJkZWdyb24iKSAlPiUgCiAgICBtdXRhdGUoc2luZ2xlLmNvbCA9IGEpCiAgIAp9KSAlPiUgCiAgYmluZF9yb3dzKCkKCiNmaXRzCnN0ZXBSLjF2YXIuZml0IDwtIGxhcHBseShyZWdyZXNzb3JzLCBmdW5jdGlvbihhKXsKICB0ZW1wLmRmMiA8LSBtbHIuZGYgJT4lIAogICAgdW5ncm91cCgpICU+JSAKICAgIGRwbHlyOjpzZWxlY3QoYSwgdC5oYWxmLGRlZ3JvbikKICAKICB0ZW1wLmRmMiAlPiUgCiAgICBzcGxpdCguJGRlZ3JvbikgJT4lIAogICAgbWFwKC4sZnVuY3Rpb24oYil7CiAgICAgIGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBiICU+JSBkcGx5cjo6c2VsZWN0KC1kZWdyb24pKSAKICAgIH0pIAp9KSAKYGBgCgojdGVzdGluZyBmb3Igb25lIGRlZ3JvbgpgYGB7cn0KY2xuMi4zLmRmIDwtIHRlbXAuZGYgJT4lIAogIGZpbHRlcihkZWdyb24gPT0gImNsbjIuMyIpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdCgtZHksLWRlZ3JvbikKCmxtKHQuaGFsZiB+IGdmcC5tZWFuLmJnLmFmLnN1Yi5uZXcgCiAgICsgcmZwLnN1bS5iZy5zdWIucHVuY3RhIAogICArIGFyZWEgCiAgIC0gbm8ub2Yudm94ZWxzIAogICAtIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEgCiAgICsgc3BoZXJhY2l0eQogICArIHNoYXBlCiAgICsgdm9sdW1lCiAgICAgLCBkYXRhID0gY2xuMi4zLmRmICkgJT4lIAogIHN1bW1hcnkoKQpgYGAKCiNwbG90dGluZyB0aGUgZGlmZmVyZW5jZSBpbiByMiAoZnVsbCBtb2RlbCAtIGRyb3BvdXQgbW9kZWwpCmBgYHtyfQpkZWx0YVIyLnBsdC5hbGwgPC0gYmluZF9yb3dzKGZ1bGxSLmxpc3QkZnVsbFIuZ2xhbmNlLCBzdGVwUi5saXN0JHN0ZXBSLmdsYW5jZSkgJT4lCiAgICBtdXRhdGUoYWRqLnIuc3F1YXJlZCA9IHJvdW5kKGFkai5yLnNxdWFyZWQgLCBkaWdpdHMgPSA0KSkgJT4lIAogICMgc2VwYXJhdGUoLixkZWdyb24sIGludG8gPSBjKCJkZWdyb24iLCJjb2xvbnkiKSwgc2VwID0gIi5SZXBsaWNhdGUgIikgJT4lICAKICAgIyBmaWx0ZXIocC52YWx1ZSA8IDAuMDUpICU+JSAKICAjIGdyb3VwX2J5KGRlZ3JvbiwgcmVtb3ZlZC5jb2wpICU+JSAKICBkcGx5cjo6c2VsZWN0KGRlZ3Jvbiwgci5zcXVhcmVkLCByZW1vdmVkLmNvbCkgJT4lIAogIHBpdm90X3dpZGVyKHZhbHVlc19mcm9tID0gci5zcXVhcmVkLCBuYW1lc19mcm9tID0gcmVtb3ZlZC5jb2wpICU+JSAKICByZW5hbWUoIlJhdGUgb2YgTWF0dXJhdGlvbiIgPSAiZG0iLCAKICAgICAgICAgIkdGUCIgPSAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIsCiAgICAgICAgICJBcmVhIiA9ICJhcmVhIiwKICAgICAgICAgIlB1cDEtdERpbWVyMiIgPSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIsCiAgICAgICAgICJEQVBJIiA9ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICAgICAgIlNoYXBlIiA9ICJzaGFwZSIpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IDM6OCkgJT4lIAogIG11dGF0ZSh2YWx1ZS5yYXRpbyA9IHZhbHVlLyBub25lLAogICAgICAgICB2YWx1ZS5zdWIgPSBub25lIC0gdmFsdWUpICU+JSAKICAjIGZpbHRlcihkZWdyb24gJWluJSBjKCJjbG4yLjMiLCJtT0RDLjIiLCJzdGFibGUuMyIsInN0YWJsZS4yIiwiY2xuMi40IikpICU+JSAKICAjIG11dGF0ZShkZWdyb24gPSBjYXNlX3doZW4oZGVncm9uICVpbiUgYygiY2xuMi4zIiwiY2xuMi4yIiwiY2xuMiIsImNsbjIuNCIpIH4gIkdGUC1DTE4yIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVncm9uICVpbiUgYygibU9EQy4yIiwgIm1PREMiKSAgfiAiR0ZQLW1PREMiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWdyb24gJWluJSBjKCJzdGFibGUiLCJzdGFibGUuMiIsInN0YWJsZS4zIikgfiAieWVHRlAiKSwKICAjICAgICAgICBkZWdyb24gPSBmYWN0b3IoZGVncm9uICwgbGV2ZWxzID0gYygiR0ZQLW1PREMiLCJHRlAtQ0xOMiIsInllR0ZQIikpKSAlPiUKICBtdXRhdGUoZGVncm9uID0gZmFjdG9yKGRlZ3JvbiAsIGxldmVscyA9IGMoInllR0ZQLW1PREMiLCJ5ZUdGUC1DTE4yIiwieWVHRlAiKSkpICU+JSAKICBnZ3Bsb3QoLixhZXMoeSA9IG5hbWUsIHggPSB2YWx1ZS5zdWIpKSsKICBnZW9tX2NvbCh3aWR0aCA9IDAuMikrCiAgZmFjZXRfd3JhcCh+ZGVncm9uLCBzY2FsZXMgPSAiZnJlZSIpKwogIHNjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgc3RyX3dyYXAoeCwgd2lkdGggPSAxMCkpKwogIHhsYWIoVGVYKCIkRGVsdGEocl57Mn1fe2Z1bGx9IC0gcl57Mn1fe3N0ZXB9KSIpKSsKICB5bGFiKCJSZWdyZXNzb3IgRHJvcHBlZCIpKwogIHRoZW1lX3B1YnIoKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwgCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSkKCmRlbHRhUjIucGx0LmFsbApgYGAKCiN0cmFuc2Zvcm0gZG0gYW5kIGRhcGkgaW50ZW5zaXR5CmBgYHtyfQpzdGVwUi5saXN0LnRyYW5zIDwtIHN0ZXBSLmZuKHJlZyA9IHJlZ3Jlc3NvcnMsIAogICAgICAgICBkZiA9IG1sci5kZjIgJT4lIAogICAgICAgICAgIG11dGF0ZShkbSA9IGxvZzEwKGRtKSksCiAgICAgICAgIHBydC5pbmgudHJ0ID0gIm5vbmUiLAogICAgICAgIGlkLnZhciA9ICJkZWdyb24iKQoKZnVsbFIubGlzdC50cmFucyA8LSBmdWxsTUxSLmZuKHJlZyA9IHJlZ3Jlc3NvcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICBkZiA9IG1sci5kZjIgJT4lIAogICAgICAgICAgIG11dGF0ZShkbSA9IGxvZzEwKGRtKSksCiAgICAgICAgICAgICAgICAgICAgICAgICBwcnQuaW5oLnRydCA9ICJub25lIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGlkLnZhciA9ICJkZWdyb24iKQpgYGAKCmBgYHtyfQpiaW5kX3Jvd3MoZnVsbFIubGlzdC50cmFucyRmdWxsUi5nbGFuY2UsIHN0ZXBSLmxpc3QudHJhbnMkc3RlcFIuZ2xhbmNlKSAlPiUKICAgIG11dGF0ZShhZGouci5zcXVhcmVkID0gcm91bmQoYWRqLnIuc3F1YXJlZCAsIGRpZ2l0cyA9IDQpKSAlPiUgCiAgc2VsZWN0KGRlZ3Jvbiwgci5zcXVhcmVkLCByZW1vdmVkLmNvbCkgJT4lIAogIHBpdm90X3dpZGVyKHZhbHVlc19mcm9tID0gci5zcXVhcmVkLCBuYW1lc19mcm9tID0gcmVtb3ZlZC5jb2wpICU+JSAKICByZW5hbWUoIlJhdGUgb2YgTWF0dXJhdGlvbiIgPSAiZG0iLCAKICAgICAgICAgIkdGUCBpbnRlbnNpdHkiID0gImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciLAogICAgICAgICAiQXJlYSIgPSAiYXJlYSIsCiAgICAgICAgICJQdXAxLXREaW1lciIgPSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIsCiAgICAgICAgICJUb3RhbCBEQVBJIEludC4iID0gImRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEiLAogICAgICAgICAiQ2VsbHVsYXIgU2hhcGUiID0gInNoYXBlIikgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gMzo4KSAlPiUgCiAgbXV0YXRlKHZhbHVlLnJhdGlvID0gdmFsdWUvIG5vbmUsCiAgICAgICAgIHZhbHVlLnN1YiA9IG5vbmUgLSB2YWx1ZSkgJT4lIAogICMgZmlsdGVyKGRlZ3JvbiAlaW4lIGMoImNsbjIuMyIsIm1PREMuMiIsInN0YWJsZS4zIiwic3RhYmxlLjIiLCJjbG4yLjQiKSkgJT4lIAogICMgbXV0YXRlKGRlZ3JvbiA9IGNhc2Vfd2hlbihkZWdyb24gJWluJSBjKCJjbG4yLjMiLCJjbG4yLjIiLCJjbG4yIiwiY2xuMi40IikgfiAiR0ZQLUNMTjIiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWdyb24gJWluJSBjKCJtT0RDLjIiLCAibU9EQyIpICB+ICJHRlAtbU9EQyIsCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZ3JvbiAlaW4lIGMoInN0YWJsZSIsInN0YWJsZS4yIiwic3RhYmxlLjMiKSB+ICJ5ZUdGUCIpLAogICMgICAgICAgIGRlZ3JvbiA9IGZhY3RvcihkZWdyb24gLCBsZXZlbHMgPSBjKCJHRlAtbU9EQyIsIkdGUC1DTE4yIiwieWVHRlAiKSkpICU+JQogIG11dGF0ZShkZWdyb24gPSBmYWN0b3IoZGVncm9uICwgbGV2ZWxzID0gYygiR0ZQLW1PREMiLCJHRlAtQ0xOMiIsInllR0ZQIikpKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHkgPSBuYW1lLCB4ID0gdmFsdWUuc3ViKSkrCiAgZ2VvbV9jb2wod2lkdGggPSAwLjIpKwogIGZhY2V0X3dyYXAofmRlZ3Jvbiwgc2NhbGVzID0gImZyZWUiKSsKICB0aGVtZV9wdWJyKCkrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApKSsKICAjIHNjYWxlX3hfbG9nMTAoKSsKICB4bGFiKFRlWCgiJERlbHRhKHJeezJ9X3tmdWxsfSAtIHJeezJ9X3tzdGVwfSkiKSkrCiAgeWxhYigiUmVncmVzc29yIERyb3BwZWQiKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKCgpgYGAKCiNsb29rIGF0IHRoZSBzaWduIG9mIHRoZSBlc3RpbWF0ZXMgCmBgYHtyfQpmdWxsUi5saXN0LnRyYW5zJGZ1bGxSLmVzdCAlPiUgc3BsaXQoLiRkZWdyb24pCgpsbSh0LmhhbGYgfiByZnAubWVhbi5iZy5zdWIucHVuY3RhICsgZG0gKyBnZnAubWVhbi5iZy5hZi5zdWIubmV3ICsgZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSwgZGF0YSA9IG1sci5kZjIgJT4lIGZpbHRlcihkZWdyb24gPT0gIkdGUC1tT0RDIikpCmBgYAoKI3Jlc2lkdWFsIGFuYWx5c2lzIG9mIHRoZSBtb2RlbHMKYGBge3J9CiNyZXNpZHVhbCBwbG90cyBhZ2FpbnN0IHRoZSBmaXR0ZWQgdmFsdWVzCmZ1bGxNTFIuZml0ICU+JSAKICBtYXAoLixhdXRvcGxvdCkKCgojcmVzaWR1YWwgcGxvdHMgYWdhaW5zdCB0aGUgcmVncmVzc29ycwpmdWxsTUxSLmZpdCAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBwbHQuZGYgPC0gYSRtb2RlbCAlPiUgCiAgICAgIG11dGF0ZShkbSA9IGxvZzEwKGRtKSwKICAgICAgICByZXMgPSBhJHJlc2lkdWFscykgJT4lIAogICAgICBwaXZvdF9sb25nZXIoY29scyA9IDI6NykKICAgIAogICAgcGx0LmRmICU+JSAKICAgICAgZ2dwbG90KC4sYWVzKHggPSB2YWx1ZSwgeSA9IHJlcykpKwogICAgICBnZW9tX3BvaW50KCkrCiAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gInJlZDQiKSsKICAgICAgZmFjZXRfd3JhcCh+bmFtZSwgc2NhbGVzID0gImZyZWUiKSsKICAgICAgeGxhYigiUmVncmVzc29yIikrCiAgICAgIHlsYWIoIlJlc2lkdWFscyIpCiAgICAgIAogIH0pCgoKYGBgCk9ic2VydmF0aW9uczogCmZyb20gdGhlIHJlc2lkdWFsIHZzIGZpdHRlZCBwbG90czogCkZvciB0aGUgZGVncm9uIEdGUHMgdGhlIHJlc2lkdWFsIHZzIHRoZSBmaXR0ZWQgcGxvdCBsaWVzIGFyb3VuZCB0aGUgaG9yaXpvbnR0YWwgYmFuZCBhcm91bmQgMC4gCmJ1dCBmb3Igc3RhYmxlIEdGUCwgdGhlIHJlc2lkdWFsIHBsb3QgaXMgYW4gb3BlbiBmdW5uZWwgc2hhcGUuIApBY2NvcmRpbmcgdG8gcGFnZSAxMzkgaW4gdGhlIGludHJvIHRvIGxpbmVhciByZWdyZXNzaW9uOiAKVGhlIHBhdHRlcm5zIGluIHBhbmVscyBiIGFuZCBjIGluZGljYXRlIHRoYXQgdGhlIHZhcmlhbmNlIG9mIHRoZSBlcnJvcnMgaXMgbm90IGNvbnN0YW50LiBUaGUgb3V0d2FyZC1vcGVuaW5nIGZ1bm5lbCBwYXR0ZXJuIGluIHBhbmVsIGIgaW1wbGllcyB0aGF0IHRoZSB2YXJpYW5jZSBpcyBhbiBpbmNyZWFzaW5nIGZ1bmN0aW9uIG9mIHkuIApGcm9tIHRoZSByZXNpZHVhbHMgdnMgcmVncmVzc29ycyBwbG90czoKaW4geWVHRlA6IHRoZXJlIGlzIGEgc3Ryb25nIGZ1bm5lbCBzaGFwZSB3aXRoIHRoZSBHRlAgaW50ZW5zaXR5OiByZXNpZHVhbHMgaXMgbmVnYXRpdmVseSByZWxhdGVkIHRvIHRoZSBHRlAgaW50ZW5zaXR5LiAKCiN0LmhhbGYgdnMgZG0gCmBgYHtyfQptbHIuZGYgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gZG0sIHkgPSBkeSkpKwogIGdlb21fcG9pbnQoKSsKICBmYWNldF93cmFwKH5kZWdyb24sIHNjYWxlcyA9ICJmcmVlIikrCiAgc2NhbGVfeF9sb2cxMCgpCmBgYAoKdGVzdGluZyBtdWx0aXBsZSBjb2xpbmVhcml0eSB1c2luZyB0aGUgZnVsbCBtb2RlbCAKbWV0aG9kID0gdmFyaWFuY2UgaW5mbGF0aW9uIGZhY3RvcnMuIHZpZiA+IDUgZm9yIGEgcmVncmVzc29yIGlzIHByb2JsZW1hdGljCmBgYHtyfQpsaWJyYXJ5KGNhcikKCmZ1bGxSLmxpc3QkZnVsbE1MUi5maXQgJT4lIG1hcCguLHZpZikKCmBgYAoKI29ubHkgdGhlIGdmcCwgcmZwLCBkYXBpIHJlZ3Jyc3NvcnMgCmBgYHtyfQpyZWdyZXNzb3JzLmZwIDwtIGMoImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciLAogICAgICAgICAgICAgICAgICAgInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiLAogICAgICAgICAgICAgICAgICAgImRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEiKQoKc3RlcFIuZnAubGlzdCA8LSBzdGVwUi5mbihyZWcgPSByZWdyZXNzb3JzLmZwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBkZiA9IG1sci5kZjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJ0LmluaC50cnQgPSAibm9uZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWQudmFyID0gImRlZ3JvbiIpCgpmdWxsUi5mcC5saXN0IDwtIGZ1bGxNTFIuZm4ocmVncmVzc29ycyA9IHJlZ3Jlc3NvcnMuZnAsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGRmID0gbWxyLmRmMiwKICAgICAgICAgICAgICAgICAgICAgICAgICBwcnQuaW5oLnRydCA9ICJub25lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBpZC52YXIgPSAiZGVncm9uIikKYGBgCgojdmFyaWFuY2UgaW5mbGF0aW9uIGZhY3RvcgpgYGB7cn0KdmlmKGZ1bGwuZnAuZml0JGNsbjIuMykgCnZpZihmdWxsLmZwLmZpdCRjbG4yLjQpIAp2aWYoZnVsbC5mcC5maXQkbU9EQy4yKSAKdmlmKGZ1bGwuZnAuZml0JHN0YWJsZS4zKQp2aWYoZnVsbC5mcC5maXQkc3RhYmxlLjIpIApgYGAKCiNkZWx0YSByMiBmb3Igb25seSB0aGUgZmx1b3Jlc2NlbnQgcHJvdGVpbnMgYXMgdGhlIHJlZ3Jlc3NvcnMKYGBge3J9CmRlbHRhUjIucGx0IDwtIGJpbmRfcm93cyhmdWxsUi5mcC5saXN0JGZ1bGxSLmdsYW5jZSwgc3RlcFIuZnAubGlzdCRzdGVwUi5nbGFuY2UpICU+JQogICAgbXV0YXRlKGFkai5yLnNxdWFyZWQgPSByb3VuZChhZGouci5zcXVhcmVkICwgZGlnaXRzID0gNCkpICU+JSAKICAjIHNlcGFyYXRlKC4sZGVncm9uLCBpbnRvID0gYygiZGVncm9uIiwiY29sb255IiksIHNlcCA9ICIuUmVwbGljYXRlICIpICU+JSAgCiAgICMgZmlsdGVyKHAudmFsdWUgPCAwLjA1KSAlPiUgCiAgIyBncm91cF9ieShkZWdyb24sIHJlbW92ZWQuY29sKSAlPiUgCiAgZHBseXI6OnNlbGVjdChkZWdyb24sIHIuc3F1YXJlZCwgcmVtb3ZlZC5jb2wpICU+JSAKICBwaXZvdF93aWRlcih2YWx1ZXNfZnJvbSA9IHIuc3F1YXJlZCwgbmFtZXNfZnJvbSA9IHJlbW92ZWQuY29sKSAlPiUgCiAgcmVuYW1lKCJHRlAgaW50ZW5zaXR5IiA9ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiwKICAgICAgICAgIlB1cDEtdERpbWVyIiA9ICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiwKICAgICAgICAgIlRvdGFsIERBUEkgSW50LiIgPSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IDM6NSkgJT4lIAogIG11dGF0ZSh2YWx1ZS5yYXRpbyA9IHZhbHVlLyBub25lLAogICAgICAgICB2YWx1ZS5zdWIgPSBub25lIC0gdmFsdWUpICU+JSAKICAjIGZpbHRlcihkZWdyb24gJWluJSBjKCJjbG4yLjMiLCJtT0RDLjIiLCJzdGFibGUuMyIsInN0YWJsZS4yIiwiY2xuMi40IikpICU+JSAKICAjIG11dGF0ZShkZWdyb24gPSBjYXNlX3doZW4oZGVncm9uICVpbiUgYygiY2xuMi4zIiwiY2xuMi4yIiwiY2xuMiIsImNsbjIuNCIpIH4gIkdGUC1DTE4yIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVncm9uICVpbiUgYygibU9EQy4yIiwgIm1PREMiKSAgfiAiR0ZQLW1PREMiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWdyb24gJWluJSBjKCJzdGFibGUiLCJzdGFibGUuMiIsInN0YWJsZS4zIikgfiAieWVHRlAiKSwKICAjICAgICAgICBkZWdyb24gPSBmYWN0b3IoZGVncm9uICwgbGV2ZWxzID0gYygiR0ZQLW1PREMiLCJHRlAtQ0xOMiIsInllR0ZQIikpKSAlPiUKICBtdXRhdGUoZGVncm9uID0gZmFjdG9yKGRlZ3JvbiAsIGxldmVscyA9IGMoInllR0ZQLW1PREMiLCJ5ZUdGUC1DTE4yIiwieWVHRlAiKSkpICU+JSAKICBnZ3Bsb3QoLixhZXMoeSA9IG5hbWUsIHggPSB2YWx1ZS5zdWIpKSsKICBnZW9tX2NvbCh3aWR0aCA9IDAuMikrCiAgZmFjZXRfd3JhcCh+ZGVncm9uLCBzY2FsZXMgPSAiZnJlZSIpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSsKICAjIHNjYWxlX3hfbG9nMTAoKSsKICB4bGFiKFRlWCgiJERlbHRhKHJeezJ9X3tmdWxsfSAtIHJeezJ9X3tzdGVwfSkiKSkrCiAgeWxhYigiUmVncmVzc29yIERyb3BwZWQiKSsKICB0aGVtZV9wdWJyKCkrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpCgpkZWx0YVIyLnBsdApgYGAKI3Jlc3BvbnNlID09IGR5IGluc3RlYWQgb2YgdC5oYWxmIApgYGB7cn0KYmluZF9yb3dzKGZ1bGxSLmZwLmxpc3QkZnVsbFIuZ2xhbmNlLCBzdGVwUi5mcC5saXN0JHN0ZXBSLmdsYW5jZSkgJT4lCiAgICBtdXRhdGUoYWRqLnIuc3F1YXJlZCA9IHJvdW5kKGFkai5yLnNxdWFyZWQgLCBkaWdpdHMgPSA0KSkgJT4lIAogICMgc2VwYXJhdGUoLixkZWdyb24sIGludG8gPSBjKCJkZWdyb24iLCJjb2xvbnkiKSwgc2VwID0gIi5SZXBsaWNhdGUgIikgJT4lICAKICAgZmlsdGVyKHAudmFsdWUgPCAwLjA1KSAlPiUgCiAgIyBncm91cF9ieShkZWdyb24sIHJlbW92ZWQuY29sKSAlPiUgCiAgc2VsZWN0KGRlZ3Jvbiwgci5zcXVhcmVkLCByZW1vdmVkLmNvbCkgJT4lIAogIHBpdm90X3dpZGVyKHZhbHVlc19mcm9tID0gci5zcXVhcmVkLCBuYW1lc19mcm9tID0gcmVtb3ZlZC5jb2wpICU+JSAKICByZW5hbWUoIkdGUCBpbnRlbnNpdHkiID0gImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciLAogICAgICAgICAiUHVwMS10RGltZXIiID0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiLAogICAgICAgICAiVG90YWwgREFQSSBJbnQuIiA9ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIikgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gMzo1KSAlPiUgCiAgbXV0YXRlKHZhbHVlLnJhdGlvID0gdmFsdWUvIG5vbmUsCiAgICAgICAgIHZhbHVlLnN1YiA9IG5vbmUgLSB2YWx1ZSkgJT4lIAogICBmaWx0ZXIoZGVncm9uICVpbiUgYygiY2xuMi4zIiwibU9EQy4yIiwic3RhYmxlLjMiLCJzdGFibGUuMiIsImNsbjIuNCIpKSAlPiUgCiAgIyBtdXRhdGUoZGVncm9uID0gY2FzZV93aGVuKGRlZ3JvbiAlaW4lIGMoImNsbjIuMyIsImNsbjIuMiIsImNsbjIiLCJjbG4yLjQiKSB+ICJHRlAtQ0xOMiIsCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIsICJtT0RDIikgIH4gIkdGUC1tT0RDIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlIiwic3RhYmxlLjIiLCJzdGFibGUuMyIpIH4gInllR0ZQIiksCiAgIyAgICAgICAgZGVncm9uID0gZmFjdG9yKGRlZ3JvbiAsIGxldmVscyA9IGMoIkdGUC1tT0RDIiwiR0ZQLUNMTjIiLCJ5ZUdGUCIpKSkgJT4lCiAgIyBtdXRhdGUoZGVncm9uID0gZmFjdG9yKGRlZ3JvbiAsIGxldmVscyA9IGMoIkdGUC1tT0RDIiwiR0ZQLUNMTjIiLCJ5ZUdGUCIpKSkgJT4lIAogIGdncGxvdCguLGFlcyh5ID0gbmFtZSwgeCA9IHZhbHVlLnN1YikpKwogIGdlb21fY29sKHdpZHRoID0gMC4yKSsKICBmYWNldF93cmFwKH5kZWdyb24sIHNjYWxlcyA9ICJmcmVlIikrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpKwogICMgc2NhbGVfeF9sb2cxMCgpKwogIHhsYWIoVGVYKCIkRGVsdGEocl57Mn1fe2Z1bGx9IC0gcl57Mn1fe3N0ZXB9KSIpKSsKICB5bGFiKCJSZWdyZXNzb3IgRHJvcHBlZCIpKwogIHRoZW1lX3B1YnIoKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKYGBgCgoKI1dpdGggdGhlIHByb3RlaW4gaW5oaWJpdG9ycwpgYGB7cn0KI3dpdGggNiByZWdyZXNzb3JzCnN0ZXBSLnBydEluaC5saXN0IDwtIHN0ZXBSLmZuKHJlZyA9IHJlZ3Jlc3NvcnMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZiA9IG1sci5kZiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBydC5pbmgudHJ0ID0gYygiZG1zbzEiLCJkbXNvMiIsIjF1TSIsIjIuNXVNIiwiNXVNIiwiNTB1TSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQudmFyID0gInRyZWF0bWVudCIpCmZ1bGxSLnBydEluaC5saXN0IDwtIGZ1bGxNTFIuZm4ocmVnID0gcmVncmVzc29ycywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRmID0gbWxyLmRmLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJ0LmluaC50cnQgPSBjKCJkbXNvMSIsImRtc28yIiwiMXVNIiwiMi41dU0iLCI1dU0iLCI1MHVNIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZC52YXIgPSAidHJlYXRtZW50IikKCiN3aXRoIGp1c3QgZmx1b3JlY2VudCBwcm90ZWlucwpzdGVwUi5wcnRJbmguZnAubGlzdCA8LSBzdGVwUi5mbihyZWcgPSByZWdyZXNzb3JzLmZwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGYgPSBtbHIuZGYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcnQuaW5oLnRydCA9IGMoImRtc28xIiwiZG1zbzIiLCIxdU0iLCIyLjV1TSIsIjV1TSIsIjUwdU0iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkLnZhciA9ICJ0cmVhdG1lbnQiKQpmdWxsUi5wcnRJbmguZnAubGlzdCA8LSBmdWxsTUxSLmZuKHJlZyA9IHJlZ3Jlc3NvcnMuZnAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZiA9IG1sci5kZiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBydC5pbmgudHJ0ID0gYygiZG1zbzEiLCJkbXNvMiIsIjF1TSIsIjIuNXVNIiwiNXVNIiwiNTB1TSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQudmFyID0gInRyZWF0bWVudCIpCgpgYGAKCnBsb3RzCmBgYHtyfQojd2l0aCA2IHJlZ3Jlc3NvcnMKYmluZF9yb3dzKGZ1bGxSLnBydEluaC5saXN0JGZ1bGxSLmdsYW5jZSwgc3RlcFIucHJ0SW5oLmxpc3Qkc3RlcFIuZ2xhbmNlKSAlPiUKICAgIG11dGF0ZShhZGouci5zcXVhcmVkID0gcm91bmQoYWRqLnIuc3F1YXJlZCAsIGRpZ2l0cyA9IDQpKSAlPiUgCiAgc2VsZWN0KHRyZWF0bWVudCwgci5zcXVhcmVkLCByZW1vdmVkLmNvbCkgJT4lIAogIHBpdm90X3dpZGVyKHZhbHVlc19mcm9tID0gci5zcXVhcmVkLCBuYW1lc19mcm9tID0gcmVtb3ZlZC5jb2wpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IDM6OCkgJT4lIAogIG11dGF0ZSh2YWx1ZS5yYXRpbyA9IHZhbHVlLyBub25lLAogICAgICAgICB2YWx1ZS5zdWIgPSBub25lIC0gdmFsdWUpICU+JSAKICBnZ3Bsb3QoLixhZXMoeSA9IG5hbWUsIHggPSB2YWx1ZS5zdWIpKSsKICBnZW9tX2NvbCgpKwogIGZhY2V0X3dyYXAofmZhY3Rvcih0cmVhdG1lbnQsIGxldmVscyA9IGMoImRtc28xIiwiZG1zbzIiLCIxdU0iLCIyLjV1TSIsIjV1TSIsIjUwdU0iKSksIHNjYWxlcyA9ICJmcmVlIikrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpKwogICMgc2NhbGVfeF9sb2cxMCgpKwogIHhsYWIoVGVYKCIkRGVsdGEocl57Mn1fe2Z1bGx9IC0gcl57Mn1fe3N0ZXB9KSIpKSsKICB5bGFiKCJyZWdyZXNzb3IgZHJvcHBlZCIpCgojd2l0aCAzIGZsdW9yZXNjZW50IHByb3RlaW5zCmJpbmRfcm93cyhmdWxsUi5wcnRJbmguZnAubGlzdCRmdWxsUi5nbGFuY2UsIHN0ZXBSLnBydEluaC5mcC5saXN0JHN0ZXBSLmdsYW5jZSkgJT4lCiAgICBtdXRhdGUoYWRqLnIuc3F1YXJlZCA9IHJvdW5kKGFkai5yLnNxdWFyZWQgLCBkaWdpdHMgPSA0KSkgJT4lIAogIHNlbGVjdCh0cmVhdG1lbnQsIHIuc3F1YXJlZCwgcmVtb3ZlZC5jb2wpICU+JSAKICBwaXZvdF93aWRlcih2YWx1ZXNfZnJvbSA9IHIuc3F1YXJlZCwgbmFtZXNfZnJvbSA9IHJlbW92ZWQuY29sKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAzOjUpICU+JSAKICBtdXRhdGUodmFsdWUucmF0aW8gPSB2YWx1ZS8gbm9uZSwKICAgICAgICAgdmFsdWUuc3ViID0gbm9uZSAtIHZhbHVlKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHkgPSBuYW1lLCB4ID0gdmFsdWUuc3ViKSkrCiAgZ2VvbV9jb2woKSsKICBmYWNldF93cmFwKH5mYWN0b3IodHJlYXRtZW50LCBsZXZlbHMgPSBjKCJkbXNvMSIsImRtc28yIiwiMXVNIiwiMi41dU0iLCI1dU0iLCI1MHVNIikpLCBzY2FsZXMgPSAiZnJlZSIpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSsKICAjIHNjYWxlX3hfbG9nMTAoKSsKICB4bGFiKFRlWCgiJERlbHRhKHJeezJ9X3tmdWxsfSAtIHJeezJ9X3tzdGVwfSkiKSkrCiAgeWxhYigicmVncmVzc29yIGRyb3BwZWQiKQpgYGAKCiNsb29rZWQgYXQgdGhlIG91dGxpZXJzCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCJxcGNSIikKbGlicmFyeShxcGNSKQoKUFJFU1MoZnVsbE1MUi5maXQpClBSRVNTKHN0ZXBSLmZwLmZpdFtbMl1dJGNsbjIuMykKUFJFU1Moc3RlcFIuZnAuZml0W1szXV0kY2xuMi4zKQoKbGlicmFyeShnZ2ZvcnRpZnkpCmF1dG9wbG90KGZ1bGxNTFIuZml0JGNsbjIuMykKYXV0b3Bsb3Qoc3RlcFIuZnAuZml0W1sxXV0kY2xuMi4zKQoKZnVsbE1MUi5maXQkY2xuMi4zJG1vZGVsCgpwbG90KHN0ZXBSLmZwLmZpdFtbMl1dJGNsbjIuMykKY29va3MuZGlzdGFuY2UoZnVsbE1MUi5maXQkY2xuMi4zKSAlPiUgYnJvb206OnRpZHkoKSAlPiUgYXJyYW5nZShkZXNjKHgpKQoKbWxyLmRmICU+JSBmaWx0ZXIoZGVncm9uID09ICJjbG4yLjMiKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKCkgJT4lIAogIGZpbHRlcihyb3duYW1lID09ICI5MTYiKQoKbGFwcGx5KGZ1bGxNTFIuZml0LCBhdXRvcGxvdCkKCmxhcHBseShmdWxsTUxSLmZpdCwgZnVuY3Rpb24oYSl7CiAgY29va3MuZGlzdGFuY2UoYSkgJT4lIAogICAgYnJvb206OnRpZHkoKSAlPiUgCiAgICBhcnJhbmdlKGRlc2MoeCkpCn0pIAoKYGBgCgpgYGB7cn0KY29va3MuZGlzdGFuY2UoZnVsbE1MUi5maXQkY2xuMi4zKSAlPiUgYnJvb206OnRpZHkoKSAlPiUgYXJyYW5nZShkZXNjKHgpKQoKb3V0bGllcnMuY2xuMi4zIDwtIG1sci5kZiAlPiUgZmlsdGVyKGRlZ3JvbiA9PSAiY2xuMi4zIikgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigpICU+JSAKICBmaWx0ZXIocm93bmFtZSAlaW4lIGMoICIxNzgiLCI1NjQiLCI3NjEiLCI5MTYiKSkgJT4lIHB1bGwoY2VsbC5pZCkKYGBgCgpgYGB7cn0KbGFwcGx5KGZ1bGxNTFIuZml0LCBzdW1tYXJ5KQpgYGAKCgojZGYgdG8gYmUgdXNlZCB3aXRoIHN0ZXAgZnVuY3Rpb24KYGBge3J9CnRlbXAuZGYubGlzdCA8LSBtbHIuZGYyICU+JSAKICAgIGZpbHRlcih0cmVhdG1lbnQgPT0gIm5vbmUiKSAlPiUgIAogICMgbXV0YXRlKCBkbSA9IGxvZzEwKGRtKSkgJT4lIAogIHNwbGl0KC4kZGVncm9uKQpgYGAKCgojdXNpbmcgc3RlcEFJQyBmcm9tIE1BU1MKYGBge3J9CmxpYnJhcnkoTUFTUykKCmZ1bGwuc3RlcEFJQy5tYXNzIDwtIGxhcHBseSh0ZW1wLmRmLmxpc3QsIGZ1bmN0aW9uKGEpewogIG4gPC0gbnJvdyhhKQogIGxtLm9iaiA8LSBsbSh0LmhhbGYgfiAuLCBkYXRhID0gYSAlPiUgCiAgICAgZHBseXI6OnNlbGVjdChyZWdyZXNzb3JzLAogICAgICAgICAgICAgICAgICAgdC5oYWxmLAogICAgICAgICAgICAgICAgICAgLWR5LCAKICAgICAgICAgICAgICAgICAgIC10cmVhdG1lbnQpKQogICAgIAogc3RlcEFJQyhvYmplY3QgPSBsbS5vYmosIAogICAgIGRpcmVjdGlvbiA9ICJiYWNrd2FyZCIsIAogICAgIHRyYWNlID0gVCkKfSkKCmZ1bGwuc3RlcEFJQy5tYXNzICU+JSBtYXAoLixicm9vbTo6dGlkeSkKCmBgYAoKI3N0ZXAgQUlDIHdpdGggYWxsIHRoZSBmcCBtYXJrZXJzICsgY2VsbCBzaGFwZSAKYGBge3J9CmZ1bGwuc3RlcEFJQyA8LSBsYXBwbHkodGVtcC5kZi5saXN0LCBmdW5jdGlvbihhKXsKICBuIDwtIG5yb3coYSkKIHN0ZXAobG0odC5oYWxmIH4gLiwgZGF0YSA9IGEgJT4lIAogICAgIGRwbHlyOjpzZWxlY3QocmVncmVzc29ycywKICAgICAgICAgICAgICAgICAgIHQuaGFsZiwKICAgICAgICAgICAgICAgICAgIC1keSwgCiAgICAgICAgICAgICAgICAgICAtdHJlYXRtZW50KSksIAogICAgIGRpcmVjdGlvbiA9ICJiYWNrd2FyZCIsIAogICAgIHRyYWNlID0gVCwKICAgICAjIGsgPSBsb2cobiksCiAgICAgayA9MiApICNrID0gMiB3aGVuIHNtYWxsIGRhdGFzZXQgYW5kIGsgPSBsb2cobikgd2hlcmUgbiA9IG5vLiBvZiBvYnNlcnZhdGlvbnMgZm9yIHdoZW4gdGhlIGRhdGFzZXQgaXMgbGFyZ2UKfSkKCgpmdWxsLnN0ZXBBSUMgJT4lIAogIG1hcCguLCBicm9vbTo6Z2xhbmNlKSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJzYW1wbGUiKSAKICAjIGZpbHRlcihzYW1wbGUgJWluJSBjKCJtT0RDLjIiLCJjbG4yLjMiLCJjbG4yLjQiLCJzdGFibGUuMiIsInN0YWJsZS4zIikpCgpmdWxsLnN0ZXBBSUMgJT4lIAogIG1hcCguLCBicm9vbTo6dGlkeSkgCiAgIyBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpICU+JSAKICAjIGZpbHRlcihzYW1wbGUgJWluJSBjKCJtT0RDLjIiLCJjbG4yLjMiLCJjbG4yLjQiLCJzdGFibGUuMiIsInN0YWJsZS4zIiksIAogICAgICAgICAjIHAudmFsdWUgPCAwLjA1KSAlPiUgCgpmdWxsLnN0ZXBBSUMgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSRhbm92YSAKICB9KSAlPiUgCiAgYmluZF9yb3dzKC4sLmlkID0gImRlZ3JvbiIpICU+JSAKICBtdXRhdGUoU3RlcCA9IGFzLmNoYXJhY3RlcihTdGVwKSwgCiAgICAgICAgIFN0ZXAgPSBpZmVsc2UoU3RlcCA9PSAiIiwgIkZ1bGwiLFN0ZXApKSAlPiUgCiAgZ3JvdXBfYnkoZGVncm9uKSAlPiUgCiAgbXV0YXRlKGRlbC5haWMgPSBBSUNbMV0tQUlDKSAKCgpmdWxsLnN0ZXBBSUMuZnAgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSRhbm92YSAKICB9KSAlPiUgCiAgYmluZF9yb3dzKC4sLmlkID0gImRlZ3JvbiIpICU+JSAKICBtdXRhdGUoU3RlcCA9IGFzLmNoYXJhY3RlcihTdGVwKSwgCiAgICAgICAgIFN0ZXAgPSBpZmVsc2UoU3RlcCA9PSAiIiwgIkZ1bGwiLFN0ZXApKSAlPiUgCiAgZ3JvdXBfYnkoZGVncm9uKSAlPiUgCiAgbXV0YXRlKGRlbC5haWMgPSBBSUNbMV0tQUlDKSAKCmBgYAoKI1Bsb3QgdGhlIGFpYyBkaWZmZXJlbmNlIGF0IGVhY2ggc3RlcApgYGB7cn0KZnVsbC5zdGVwQUlDICU+JSAKICBtYXAoLixmdW5jdGlvbihhKXsKICAgIGEkYW5vdmEgCiAgfSkgJT4lIAogIGJpbmRfcm93cyguLC5pZCA9ICJkZWdyb24iKSAlPiUgCiAgbXV0YXRlKFN0ZXAgPSBhcy5jaGFyYWN0ZXIoU3RlcCksIAogICAgICAgICBTdGVwID0gaWZlbHNlKFN0ZXAgPT0gIiIsICJGdWxsIixTdGVwKSkgJT4lIAogIGdyb3VwX2J5KGRlZ3JvbikgJT4lIAogIG11dGF0ZShkZWwuYWljID0gQUlDWzFdLUFJQykgJT4lIAogIHNlbGVjdChkZWdyb24sIFN0ZXAsIGRlbC5haWMpICU+JSAKICBzcGxpdCguJGRlZ3JvbikgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYVtucm93KGEpLF0gJT4lIAogICAgICBtdXRhdGUobW9kZWwgPSAicmVkdWNlZCIpCiAgfSkgJT4lIAogIGJpbmRfcm93cyguaWQgPSAiZGVncm9uIikgJT4lIAogIG11dGF0ZShkZWdyb24gPSBmYWN0b3IoZGVncm9uLCBsZXZlbHMgPSBjKCJHRlAtbU9EQyIsICJHRlAtQ0xOMiIsInllR0ZQIikpKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHggPSBkZWwuYWljLCB5ID0gZGVncm9uKSkrCiAgZ2VvbV9jb2wod2lkdGggPSAwLjIpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSsKICAjIHNjYWxlX3hfbG9nMTAoKSsKICB4bGFiKFRlWCgiJERlbHRhKEFJQ197ZnVsbH0gLSBBSUNfe3N0ZXB9KSIpKSsKICB5bGFiKCJSZWdyZXNzb3IgRHJvcHBlZCIpKwogIHRoZW1lX3B1YnIoKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKCmBgYAoKI3N0ZXAgQUlDIHdpdGggb25seSB0aGUgZmx1b3Jlc2NlbnQgbWFya2VycyAKYGBge3J9CmZ1bGwuc3RlcEFJQy5mcCA8LSBsYXBwbHkodGVtcC5kZi5saXN0LCBmdW5jdGlvbihhKXsKICBuIDwtIG5yb3coYSkKIHN0ZXAobG0odC5oYWxmIH4gLiwgZGF0YSA9IGEgJT4lIAogICAgIGRwbHlyOjpzZWxlY3QocmVncmVzc29ycy5mcCwKICAgICAgICAgICAgICAgICAgIHQuaGFsZiwKICAgICAgICAgICAgICAgICAgIC1keSwgCiAgICAgICAgICAgICAgICAgICAtdHJlYXRtZW50KSksIAogICAgIGRpcmVjdGlvbiA9ICJiYWNrd2FyZCIsIAogICAgIHRyYWNlID0gVCwKICAgICBrID0gMikKfSkKCiNsb29raW5nIGF0IHdoaWNoIHJlZ3Jlc3NvciBjb250cmlidXRlcyB0byB0aGUgb3ZlcmFsbCB2YXJpYWJpbGl0eSAKZnVsbC5zdGVwQUlDLmZwICU+JSAKICBtYXAoLiwgYnJvb206OnRpZHkpIAogICMgZmlsdGVyKHNhbXBsZSAlaW4lIGMoIm1PREMuMiIsImNsbjIuMyIsImNsbjIuNCIsInN0YWJsZS4yIiwic3RhYmxlLjMiKSkgJT4lIAogICMgc3BsaXQoLiRzYW1wbGUpCgojbW9kZWwgZml0IHN0YXRzCmZ1bGwuc3RlcEFJQy5mcCAlPiUgCiAgbWFwKC4sIGJyb29tOjpnbGFuY2UpICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpCgoKZnVsbC5zdGVwQUlDLmZwICU+JSAKICBtYXAoLixmdW5jdGlvbihhKXsKICAgIGEkYW5vdmEgCiAgfSkgJT4lIAogIGJpbmRfcm93cyguLC5pZCA9ICJkZWdyb24iKSAlPiUgCiAgbXV0YXRlKFN0ZXAgPSBhcy5jaGFyYWN0ZXIoU3RlcCksIAogICAgICAgICBTdGVwID0gaWZlbHNlKFN0ZXAgPT0gIiIsICJGdWxsIixTdGVwKSkgJT4lIAogIGdyb3VwX2J5KGRlZ3JvbikgJT4lIAogIG11dGF0ZShkZWwuYWljID0gQUlDLUFJQ1sxXSkgCmBgYAoKVmFyaWFuY2UgaW4gdC1oYWxmIGV4cGxhaW5lZCBieSBlYWNoIHJlZ3Jlc3Nvcgp1c2luZyBhbm92YQoKYGBge3J9CmZ1bGwuc3RlcEFJQy5mcCAlPiUgCiAgbWFwKC4sIGFub3ZhICU+JSBhcy5kYXRhLmZyYW1lKSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJzYW1wbGUiKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJwcmVkaWN0b3IiKSAlPiUgCiAgIyBmaWx0ZXIoc2FtcGxlICVpbiUgYygibU9EQy4yIiwiY2xuMi4zIiwiY2xuMi40Iiwic3RhYmxlLjIiLCJzdGFibGUuMyIpKSAlPiUgCiAgZ3JvdXBfYnkoc2FtcGxlKSAlPiUgCiAgbXV0YXRlKHZhci5leHAgPSAodmFsdWUuU3VtLlNxL3N1bSh2YWx1ZS5TdW0uU3EpKSoxMDApICU+JSAKICBzcGxpdCguJHNhbXBsZSkKCnZhci5leHBsYWluZWQgPC0gZnVsbC5zdGVwQUlDICU+JSAKICBtYXAoLiwgYW5vdmEgJT4lIGFzLmRhdGEuZnJhbWUpICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInByZWRpY3RvciIpICU+JSAKICAjIGZpbHRlcihzYW1wbGUgJWluJSBjKCJtT0RDLjIiLCJjbG4yLjMiLCJjbG4yLjQiLCJzdGFibGUuMiIsInN0YWJsZS4zIikpICU+JSAKICBncm91cF9ieShzYW1wbGUpICU+JSAKICBtdXRhdGUodmFyLmV4cCA9ICh2YWx1ZS5TdW0uU3Evc3VtKHZhbHVlLlN1bS5TcSkpKjEwMCwgCiAgICAgICAgIHByZWRpY3RvciA9IHN0cl9zcGxpdChwcmVkaWN0b3IsIHBhdHRlcm4gPSAiXFwuXFwuXFwuIiwgc2ltcGxpZnkgPSBUKVssMV0sIAogICAgICAgICBwcmVkaWN0b3IgPSBjYXNlX3doZW4ocHJlZGljdG9yID09ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiB+ICJHRlAiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAiYXJlYSIgfiAiQXJlYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0b3IgPT0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiIH4gIlB1cDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID09ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiB+ICJETkEiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAic2hhcGUiIH4gIlNoYXBlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0b3IgPT0gImRtIiB+ICJSYXRlIG9mIE1hdHVyYXRpb24iCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRX5wcmVkaWN0b3IpKSAlPiUgCiAgc3BsaXQoLiRzYW1wbGUpCgp2YXIuZXhwbGFpbmVkCmBgYAoKI3Bsb3R0aW5nIHRoZSB2YXJpYW5jZSBleHBsYWluZWQgCmBgYHtyfQpyZW1haW4ucmVnIDwtIGRhdGEuZnJhbWUoc2FtcGxlID0gYygieWVHRlAtQ0xOMiIsInllR0ZQLUNMTjIiLCJ5ZUdGUCIsInllR0ZQIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID0gYygiUmF0ZSBvZiBNYXR1cmF0aW9uIiwgIlNoYXBlIiwiU2hhcGUiLCJQdXAxIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgdmFyLmV4cCA9IHJlcCgwLDQpLAogICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUuUHIuLkYuID0gcmVwKDAsNCkpCnZhci5leHAucGx0IDwtIHZhci5leHBsYWluZWQgJT4lIAogIGJpbmRfcm93cygpICU+JSAKICBiaW5kX3Jvd3MoLixyZW1haW4ucmVnKSAlPiUgCiAgZmlsdGVyKHByZWRpY3RvciAhPSAiUmVzaWR1YWxzIikgJT4lIAogIGRwbHlyOjpzZWxlY3Qoc2FtcGxlLCBwcmVkaWN0b3IsIHZhci5leHAsdmFsdWUuUHIuLkYuKSAlPiUgCiAgbXV0YXRlKHNhbXBsZSA9IGZhY3RvcihzYW1wbGUgLCBsZXZlbHMgPSBjKCJ5ZUdGUC1tT0RDIiwieWVHRlAtQ0xOMiIsInllR0ZQIikpKSAlPiUgCiAgIyBtdXRhdGUodmFyLnBhbCA9IGlmZWxzZSh2YWx1ZS5Qci4uRi4gPCAwLjA1LCAiPDAuMDUiLCI+MC4wNSIpKSAlPiUgCiAgYXJyYW5nZShzYW1wbGUpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IHByZWRpY3RvciwgeSA9IHZhci5leHAgKSkrCiAgZ2VvbV9jb2wod2lkdGggPSAwLjUpKwogIGZhY2V0X3dyYXAofnNhbXBsZSwgc2NhbGVzID0gImZyZWUiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cl93cmFwKHgsIHdpZHRoID0gNSkpKwogIHRoZW1lX3B1YnIoKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuMSksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgeWxpbSgwLDIwKSsKICB5bGFiKCJWYXJpYW5jZSBleHBsYWluZWQgKCUpIikrCiAgeGxhYigiQ2VsbHVsYXIgZmVhdHVyZXMiKQp2YXIuZXhwLnBsdApgYGAKCiNzdGVwQUlDIHdpdGggcHJvdGVhc29tZSBpbmhpYml0aW9uIGV4cGVyaW1lbnRzCldpdGggYWxsIGZwIHJlZ3Jlc3NvcnMKYGBge3J9CnRlbXAuZGYubGlzdC5kbXNvIDwtIG1sci5kZiAlPiUgCiAgICBmaWx0ZXIodHJlYXRtZW50ICE9ICJub25lIikgJT4lICAKICBzcGxpdCguJHRyZWF0bWVudCkKCmZ1bGwuc3RlcEFJQy5mcC5kbXNvIDwtIGxhcHBseSh0ZW1wLmRmLmxpc3QuZG1zbywgZnVuY3Rpb24oYSl7CiBzdGVwKGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMuZnAsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpLCAKICAgICBkaXJlY3Rpb24gPSAiYmFja3dhcmQiLCB0cmFjZSA9IFQpCn0pCgpsYXBwbHkoZnVsbC5zdGVwQUlDLmZwLmRtc28sIHN1bW1hcnkpICU+JSBtYXAoLiwgYnJvb206OnRpZHkpICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpICU+JSAKICBzcGxpdCguJHNhbXBsZSkKCmxhcHBseShmdWxsLnN0ZXBBSUMuZnAuZG1zbywgc3VtbWFyeSkgJT4lIG1hcCguLCBicm9vbTo6Z2xhbmNlKSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJzYW1wbGUiKSAlPiUgCiAgc3BsaXQoLiRzYW1wbGUpCmBgYAoKd2l0aCBmcCByZWdyZXNzb3JzICsgY2VsbHVhciBzaGFwZSAKYGBge3J9CnRlbXAuZGYubGlzdC5kbXNvIDwtIG1sci5kZiAlPiUgCiAgICBmaWx0ZXIodHJlYXRtZW50ICE9ICJub25lIikgJT4lICAKICBzcGxpdCguJHRyZWF0bWVudCkKCmZ1bGwuc3RlcEFJQy5kbXNvIDwtIGxhcHBseSh0ZW1wLmRmLmxpc3QuZG1zbywgZnVuY3Rpb24oYSl7CiBzdGVwKGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMuZnAsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpLCAKICAgICBkaXJlY3Rpb24gPSAiYmFja3dhcmQiLCB0cmFjZSA9IFQpCn0pCgpsYXBwbHkoZnVsbC5zdGVwQUlDLmRtc28sIHN1bW1hcnkpICU+JSBtYXAoLiwgYnJvb206OnRpZHkpICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpICU+JSAKICBzcGxpdCguJHNhbXBsZSkKCmxhcHBseShmdWxsLnN0ZXBBSUMuZG1zbywgc3VtbWFyeSkgJT4lIG1hcCguLCBicm9vbTo6Z2xhbmNlKSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJzYW1wbGUiKSAlPiUgCiAgc3BsaXQoLiRzYW1wbGUpIAoKYGBgCgpWYXJpYW5jZSBpbiB0LWhhbGYgZXhwbGFpbmVkIGJ5IGVhY2ggcmVncmVzc29yCmBgYHtyfQpmdWxsLnN0ZXBBSUMuZG1zbyAlPiUgCiAgbWFwKC4sIGFub3ZhICU+JSBhcy5kYXRhLmZyYW1lKSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJzYW1wbGUiKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJwcmVkaWN0b3IiKSAlPiUgCiAgIyBmaWx0ZXIoc2FtcGxlICVpbiUgYygibU9EQy4yIiwiY2xuMi4zIiwiY2xuMi40Iiwic3RhYmxlLjIiLCJzdGFibGUuMyIpKSAlPiUgCiAgZ3JvdXBfYnkoc2FtcGxlKSAlPiUgCiAgbXV0YXRlKHZhci5leHAgPSAodmFsdWUuU3VtLlNxL3N1bSh2YWx1ZS5TdW0uU3EpKSoxMDApICU+JSAKICBzcGxpdCguJHNhbXBsZSkKCmZ1bGwuc3RlcEFJQy5mcC5kbXNvICU+JSAKICBtYXAoLiwgYW5vdmEgJT4lIGFzLmRhdGEuZnJhbWUpICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInByZWRpY3RvciIpICU+JSAKICAjIGZpbHRlcihzYW1wbGUgJWluJSBjKCJtT0RDLjIiLCJjbG4yLjMiLCJjbG4yLjQiLCJzdGFibGUuMiIsInN0YWJsZS4zIikpICU+JSAKICBncm91cF9ieShzYW1wbGUpICU+JSAKICBtdXRhdGUodmFyLmV4cCA9ICh2YWx1ZS5TdW0uU3Evc3VtKHZhbHVlLlN1bS5TcSkpKjEwMCkgJT4lIAogIHNwbGl0KC4kc2FtcGxlKQoKYGBgCgoKCiN1c2luZyByZWdzdWJzZXRzCmBgYHtyfQpsaWJyYXJ5KGxlYXBzKQpgYGAKCmBgYHtyfQpmdWxsLnJlZ1N1Yi5mcCA8LSBsYXBwbHkodGVtcC5kZi5saXN0LCBmdW5jdGlvbihhKXsKICBuIDwtIG5yb3coYSkKIHJlZ3N1YnNldHModC5oYWxmIH4gLiwgZGF0YSA9IGEgJT4lIAogICAgIGRwbHlyOjpzZWxlY3QocmVncmVzc29ycy5mcCwKICAgICAgICAgICAgICAgICAgIHQuaGFsZiwKICAgICAgICAgICAgICAgICAgIC1keSwgCiAgICAgICAgICAgICAgICAgICAtdHJlYXRtZW50KSwgCiAgICAgbnZtYXggPSBOVUxMKQp9KQoKcmVnU3ViLnN1bW1hcnkgPC0gZnVsbC5yZWdTdWIuZnAgJT4lIG1hcCguLHN1bW1hcnkpCgpsYXBwbHkocmVnU3ViLnN1bW1hcnksIGZ1bmN0aW9uKGEpewogIGRhdGEuZnJhbWUobW9kZWwgPSBhJG91dG1hdCwgCiAgICAgICAgICAgICBjcCA9IGEkY3AsCiAgICAgICAgICAgICBiaWMgPSBhJGJpYykKfSkgJT4lIGJpbmRfcm93cyguaWQgPSAiZGVncm9uIikgJT4lIAogIGdyb3VwX2J5KGRlZ3JvbikgJT4lIAogIGFycmFuZ2UoZGVncm9uLCBjcCkKYGBgCgpgYGB7cn0KZnVsbC5yZWdTdWIgPC0gbGFwcGx5KHRlbXAuZGYubGlzdCwgZnVuY3Rpb24oYSl7CiAgbiA8LSBucm93KGEpCiAgCiAgCiByZWdzdWJzZXRzKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCksIAogICAgIG52bWF4ID0gTlVMTCkKfSkKCnJlZ1N1Yi5zdW1tYXJ5MiA8LSBmdWxsLnJlZ1N1YiAlPiUgbWFwKC4sc3VtbWFyeSkKCmxhcHBseShyZWdTdWIuc3VtbWFyeTIsIGZ1bmN0aW9uKGEpewogIGRhdGEuZnJhbWUobW9kZWwgPSBhJG91dG1hdCwgCiAgICAgICAgICAgICBjcCA9IGEkY3AsCiAgICAgICAgICAgICBiaWMgPSBhJGJpYykKfSkgJT4lIGJpbmRfcm93cyguaWQgPSAiZGVncm9uIikgJT4lIAogIGdyb3VwX2J5KGRlZ3JvbikgJT4lIAogIGFycmFuZ2UoZGVncm9uLCBiaWMKICAgICAgICAgICkgJT4lIHNwbGl0KC4kZGVncm9uKQpgYGAKCgoKI3Bsb3RzOiAKYGBge3J9CmdmcC42LmNvci5wbHQgPC0gbWxyLmRmICU+JQogIG11dGF0ZShkbSA9IGxvZzEwKGRtKSkgJT4lIAogIGZpbHRlcihkZWdyb24gJWluJSBjKCJtT0RDLjIiLCAiY2xuMi4zIiwgImNsbjIuNCIsICJzdGFibGUuMiIsICJzdGFibGUuMyIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwKICAgICAgICAgcmVncmVzc29ycywKICAgICAgICAgZGVncm9uKSAlPiUKICByZW5hbWUoCiAgICAiR0ZQIiA9ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiwKICAgICJQdXAxLXREaW1lciIgPSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIsCiAgICAiRE5BIiA9ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICJBcmVhIiA9ICJhcmVhIgogICkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAyOjcpICU+JQogIG11dGF0ZShkZWdyb24gPSBjYXNlX3doZW4oCiAgICAgIGRlZ3JvbiAlaW4lIGMoImNsbjIuMyIsICJjbG4yLjIiLCAiY2xuMiIsICJjbG4yLjQiKSB+ICJ5ZUdGUC1DTE4yIiwKICAgICAgZGVncm9uICVpbiUgYygibU9EQy4yIiwgIm1PREMiKSAgfiAieWVHRlAtbU9EQyIsCiAgICAgIGRlZ3JvbiAlaW4lIGMoInN0YWJsZSIsICJzdGFibGUuMiIsICJzdGFibGUuMyIpIH4gInllR0ZQIgogICAgKSwKICAgIGRlZ3JvbiA9IGZhY3RvcihkZWdyb24gLCBsZXZlbHMgPSBjKCJ5ZUdGUC1tT0RDIiwgInllR0ZQLUNMTjIiLCAieWVHRlAiKSkKICApICU+JQogIGZpbHRlcighKG5hbWUgJWluJSBjKCJzaGFwZSIsImRtIikpKSAlPiUgCiAgZ2dwbG90KC4sIGFlcyh4ID0gdmFsdWUsIHkgPSB0LmhhbGYpKSArCiAgICAgIGdncG9pbnRkZW5zaXR5OjpnZW9tX3BvaW50ZGVuc2l0eShzaXplID0gMC4yLCBndWlkZXMgPSBGKSArCiAgICAgIHN0YXRfY29yKHNpemUgPSAyKSArCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZDQiLCBzaXplID0gMC41KSsKICAgICAgZmFjZXRfd3JhcChkZWdyb24gfiBuYW1lLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSA0KSArCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBsYWJzKHggPSBOVUxMKSArCiAgICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSwKICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgyLCJtbSIpLCAKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjEpKSsKICB5bGFiKCJIYWxmLWxpZmUgW21pbi5dIikrCiAgeGxhYigiQS5VIikKICAKZ2ZwLjYuY29yLnBsdApgYGAKCmBgYHtyfQpnZnAuMy5jb3IucGx0IDwtIG1sci5kZiAlPiUKICBmaWx0ZXIoZGVncm9uICVpbiUgYygibU9EQy4yIiwgImNsbjIuMyIsICJjbG4yLjQiLCAic3RhYmxlLjIiLCAic3RhYmxlLjMiKSkgJT4lCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMuZnAsCiAgICAgICAgIGRlZ3JvbikgJT4lCiAgcmVuYW1lKAogICAgIkdGUCBpbnRlbnNpdHkiID0gImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciLAogICAgIlB1cDEtdERpbWVyIiA9ICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiwKICAgICJUb3RhbCBETkEgSW50LiIgPSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIKICApICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gMjo0KSAlPiUKICBtdXRhdGUoCiAgICBkZWdyb24gPSBjYXNlX3doZW4oCiAgICAgIGRlZ3JvbiAlaW4lIGMoImNsbjIuMyIsICJjbG4yLjQiKSB+ICJ5ZUdGUC1DTE4yIiwKICAgICAgZGVncm9uICVpbiUgYygibU9EQy4yIikgIH4gInllR0ZQLW1PREMiLAogICAgICBkZWdyb24gJWluJSBjKCJzdGFibGUuMiIsICJzdGFibGUuMyIpIH4gInllR0ZQIgogICAgKSwKICAgIGRlZ3JvbiA9IGZhY3RvcihkZWdyb24gLCBsZXZlbHMgPSBjKCJ5ZUdGUC1tT0RDIiwgInllR0ZQLUNMTjIiLCAieWVHRlAiKSkKICApICU+JQogIGdncGxvdCguLCBhZXMoeCA9IHZhbHVlLCB5ID0gdC5oYWxmKSkgKwogIGdncG9pbnRkZW5zaXR5OjpnZW9tX3BvaW50ZGVuc2l0eShzaXplID0gMC4yLCBndWlkZXMgPSBGKSArCiAgc3RhdF9jb3Ioc2l6ZSA9IDIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgICAgIGZhY2V0X3dyYXAoZGVncm9uIH4gbmFtZSwgc2NhbGVzID0gImZyZWUiKSArCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBsYWJzKHggPSBOVUxMKSArCiAgICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSwKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKSsKICB5bGFiKCJIYWxmLUxpZmUgW21pbi5dIikrCiAgeGxhYigiSW50ZW5zaXR5IFtBLlUuXSIpCgpnZnAuMy5jb3IucGx0CmBgYApHRlAgaW50ZW5zaXR5IHZzIHQtaGFsZiBjb3IgcGxvdCAKYGBge3J9CmdmcC5JbnQuY29yLnBsdCA8LSBtbHIuZGYgJT4lCiAgZmlsdGVyKGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIsICJjbG4yLjMiLCAiY2xuMi40IiwgInN0YWJsZS4yIiwgInN0YWJsZS4zIikpICU+JQogIGRwbHlyOjpzZWxlY3QodC5oYWxmLAogICAgICAgICBnZnAubWVhbi5iZy5hZi5zdWIubmV3LAogICAgICAgICBkZWdyb24pICU+JQogIG11dGF0ZSgKICAgIGRlZ3JvbiA9IGNhc2Vfd2hlbigKICAgICAgZGVncm9uICVpbiUgYygiY2xuMi4zIiwgImNsbjIuNCIpIH4gInllR0ZQLUNMTjIiLAogICAgICBkZWdyb24gJWluJSBjKCJtT0RDLjIiKSAgfiAieWVHRlAtbU9EQyIsCiAgICAgIGRlZ3JvbiAlaW4lIGMoInN0YWJsZS4yIiwgInN0YWJsZS4zIikgfiAieWVHRlAiCiAgICApLAogICAgZGVncm9uID0gZmFjdG9yKGRlZ3JvbiAsIGxldmVscyA9IGMoInllR0ZQLW1PREMiLCAieWVHRlAtQ0xOMiIsICJ5ZUdGUCIpKQogICkgJT4lCiAgZ2dwbG90KC4sIGFlcyh4ID0gZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldywgeSA9IHQuaGFsZikpICsKICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogIHN0YXRfY29yKHNpemUgPSA2KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkNCIsIHNpemUgPSAwLjUpKwogICAgICBmYWNldF93cmFwKH5kZWdyb24gLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSwKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKSsKICB5bGFiKCJIYWxmLUxpZmUgW21pbi5dIikrCiAgeGxhYigiR0ZQIEludGVuc2l0eSBbQS5VLl0iKQoKZ2ZwLkludC5jb3IucGx0CmBgYAoKI3BhdGNod29yayBmb3IgMyBjZWxsdWxhciBmZWF0dXJlcyBhbmQgdC1oYWxmCmBgYHtyIGZpZy5oZWlnaHQ9IDQsIGZpZy53aWR0aD0gNSB9CmNlbGx1bGFyLmhhbGZMaWZlLnBsdCA8LSAoZGVsdGFSMi5wbHQuYWxsL2dmcC4zLmNvci5wbHQpKwogIHBsb3RfbGF5b3V0KGd1aWRlcyA9ICJjb2xsZWN0IiwgaGVpZ2h0cyA9IGMoMC4zLDAuNykpKwogIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gIkEiKQoKY2VsbHVsYXIuaGFsZkxpZmUucGx0CmBgYAoKYGBge3J9Cmdnc2F2ZShwbG90ID0gY2VsbHVsYXIuaGFsZkxpZmUucGx0LCBmaWxlbmFtZSA9ICJjZWxsdWxhcl9oYWxmTGlmZV9jb3IucG5nIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNi41LCBoZWlnaHQgPSA4KQpnZ3NhdmUocGxvdCA9IGNlbGx1bGFyLmhhbGZMaWZlLnBsdCwgZmlsZW5hbWUgPSAiY2VsbHVsYXJfaGFsZkxpZmVfY29yLnBkZiIsIHBhdGggPSAifi9wbG90cy9wYXBlcjEvZmlndXJlcy9maWdfMi8iLCB3aWR0aCA9IDYuNSwgaGVpZ2h0ID0gOCkKYGBgCgojcGF0Y2h3b3JrIGZvciBHRlAgaW50ZW5zaXR5IGFuZCB0LWhhbGYgCmBgYHtyICB9CmdmcEludC5oYWxmTGlmZS5wbHQgPC0gKGRlbHRhUjIucGx0LmFsbC9nZnAuSW50LmNvci5wbHQpKwogIHBsb3RfbGF5b3V0KGd1aWRlcyA9ICJjb2xsZWN0IikrCiAgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiQSIpCgpnZnBJbnQuaGFsZkxpZmUucGx0CmBgYApgYGB7cn0KZ2dzYXZlKHBsb3QgPSBnZnBJbnQuaGFsZkxpZmUucGx0LCBmaWxlbmFtZSA9ICJnZnBJbnRfaGFsZkxpZmVfY29yLnBuZyIsIHBhdGggPSAifi9wbG90cy9wYXBlcjEvZmlndXJlcy9maWdfMi8iLCB3aWR0aCA9IDUuNSwgaGVpZ2h0ID0gNikKZ2dzYXZlKHBsb3QgPSBnZnBJbnQuaGFsZkxpZmUucGx0LCBmaWxlbmFtZSA9ICJnZnBJbnRfaGFsZkxpZmVfY29yLnBkZiIsIHBhdGggPSAifi9wbG90cy9wYXBlcjEvZmlndXJlcy9maWdfMi8iLCB3aWR0aCA9IDUuNSwgaGVpZ2h0ID0gNikKYGBgCgoKCiNmb3IgR1JDIHBvc3RlcgpgYGB7cn0KZ2dzYXZlKHBsb3QgPSB2YXIuZXhwLnBsdCwgZmlsZW5hbWUgPSAidmFyX2V4cGxhaW5lZC5wZGYiLHBhdGggPSAifi9wbG90cy9wYXBlcjEvZmlndXJlcy9maWdfMi8iLCB3aWR0aCA9MTIsIGhlaWdodCA9IDMpCmdnc2F2ZShwbG90ID1nZnAuSW50LmNvci5wbHQgLCBmaWxlbmFtZSA9ICJnZnBJbnRfY29yLnBkZiIscGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0xMiwgaGVpZ2h0ID0gMykKYGBgCgp3aXRoIHByb3R0ZWluIGluaGliaXRpb24KYGBge3J9CiBtbHIuZGYgJT4lCiAgbXV0YXRlKGRtID0gbG9nMTAoZG0pKSAlPiUgCiAgZmlsdGVyKGRlZ3JvbiAlaW4lIGMgKCJtT0RDIikgKSAlPiUKICAjIGZpbHRlcighKHRyZWF0bWVudCAlaW4lIGMoIm5vbmUiLCAiZG1zbzEiLCI1MHVNIikpLCAKICAgICAgICAgIyBpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAgCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMsCiAgICAgICAgIGRlZ3JvbiwKICAgICAgICAgdHJlYXRtZW50KSAlPiUKICByZW5hbWUoCiAgICAiR0ZQIiA9ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiwKICAgICJQdXAxLXREaW1lciIgPSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIsCiAgICAiRE5BIiA9ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICJBcmVhIiA9ICJhcmVhIgogICkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAyOjcpICU+JQogIG11dGF0ZShkZWdyb24gPSBjYXNlX3doZW4oCiAgICBkZWdyb24gJWluJSBjKCJtT0RDIikgIH4gInllR0ZQLW1PREMiKSwKICAgIHRyZWF0bWVudCA9IGZhY3Rvcih0cmVhdG1lbnQsIGxldmVscyA9IGMoIm5vbmUiLCJkbXNvMSIsImRtc28yIiwiMXVNIiwiMi41dU0iLCI1dU0iLCI1MHVNIikpKSAlPiUKICBmaWx0ZXIoIShuYW1lICVpbiUgYygic2hhcGUiLCJkbSIpKSkgJT4lIAogIGdncGxvdCguLCBhZXMoeCA9IHZhbHVlLCB5ID0gdC5oYWxmKSkgKwogICAgICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogICAgICBzdGF0X2NvcihzaXplID0gMikgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgICAgIGZhY2V0X2dyaWQodHJlYXRtZW50IH4gbmFtZSwgc2NhbGVzID0gImZyZWUiKSArCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBsYWJzKHggPSBOVUxMKSArCiAgICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSwKICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgyLCJtbSIpLCAKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsKICB5bGFiKCJIYWxmLUxpZmUgW21pbi5dIikrCiAgeGxhYigiQS5VIikKCmBgYAoKYGBge3J9Cm1sci5kZiAlPiUKICBtdXRhdGUoZG0gPSBsb2cxMChkbSkpICU+JSAKICBmaWx0ZXIoZGVncm9uICVpbiUgYyAoIm1PREMiKSApICU+JQogIGZpbHRlcighKHRyZWF0bWVudCAlaW4lIGMoIm5vbmUiLCAiZG1zbzEiLCI1MHVNIikpLCAKICAgICAgICAgaWZlbHNlKHRyZWF0bWVudCA9PSAiNXVNIiwgdC5oYWxmIDwgMTM4LjYyOTQsIHQuaGFsZiA9PSB0LmhhbGYpKSAlPiUgCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMsCiAgICAgICAgIGRlZ3JvbiwKICAgICAgICAgdHJlYXRtZW50KSAlPiUgCiAgZ2dwbG90KC4sYWVzKHggPSBhcmVhLCB5ID0gcmZwLm1lYW4uYmcuc3ViLnB1bmN0YSkpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYpKwogIGZhY2V0X3dyYXAofnRyZWF0bWVudCkrCiAgc3RhdF9jb3IoKQpgYGAKCgpgYGB7cn0KbWxyLmRmICU+JSAKICBmaWx0ZXIodHJlYXRtZW50ID09ICJub25lIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSkpKwogIGdlb21faGlzdG9ncmFtKCkrCiAgZmFjZXRfd3JhcCh+ZGVncm9uLCBzY2FsZXMgPSAiZnJlZSIpCmBgYAojZ2dwYWlycyAKCmBgYHtyfQojdG8gYmUgdXNlZCB3aXRoIGdncGFpcnMKbXlfZm4gPC0gZnVuY3Rpb24oZGF0YSwgbWFwcGluZywgLi4uKXsKICBwIDwtIGdncGxvdChkYXRhID0gZGF0YSwgbWFwcGluZyA9IG1hcHBpbmcpICsgCiAgICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMSkrCiAgICAjIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSwgYWxwaGEgPSAwLjEpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgIGNvbG9yPSJyZWQ0Iiwgc2UgPSBGQUxTRSwgbHdkID0gMC41KSsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKICBwCn0KCmdmcC5hcmVhLmNvci5nZ1BhaXIgPC0gbWxyLmRmICU+JQogIGZpbHRlcihkZWdyb24gJWluJSBjKCJtT0RDLjIiLCAiY2xuMi4zIiwgImNsbjIuNCIsICJzdGFibGUuMiIsICJzdGFibGUuMyIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwKICAgICAgICAgcmVncmVzc29ycywKICAgICAgICAgZGVncm9uKSAlPiUKICByZW5hbWUoCiAgICAiR0ZQIiA9ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiwKICAgICJQdXAxLXREaW1lciIgPSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIsCiAgICAiRE5BIiA9ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICJBcmVhIiA9ICJhcmVhIgogICkgJT4lCiAgZHBseXI6OnNlbGVjdChBcmVhLCBETkEsIGBQdXAxLXREaW1lcmAsR0ZQLGRlZ3JvbiApICU+JSAKICBtdXRhdGUoCiAgICBkZWdyb24gPSBjYXNlX3doZW4oCiAgICAgIGRlZ3JvbiAlaW4lIGMoImNsbjIuMyIsICJjbG4yLjQiKSB+ICJ5ZUdGUC1DTE4yIiwKICAgICAgZGVncm9uICVpbiUgYygibU9EQy4yIikgIH4gInllR0ZQLW1PREMiLAogICAgICBkZWdyb24gJWluJSBjKCJzdGFibGUuMiIsICJzdGFibGUuMyIpIH4gInllR0ZQIgogICAgKSwKICAgIGRlZ3JvbiA9IGZhY3RvcihkZWdyb24gLCBsZXZlbHMgPSBjKCJ5ZUdGUC1tT0RDIiwgInllR0ZQLUNMTjIiLCAieWVHRlAiKSkKICApICU+JQogIHNwbGl0KC4kZGVncm9uKSAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBhICU+JSAKICAgICAgZ2dwYWlycyguLAogICAgICAgICAgIyBsZWdlbmQgPSA1LAogICAgICAgICAgY29sdW1ucyA9IDE6NCwKICAgICAgICAgICMgbWFwcGluZyA9IGdncGxvdDI6OmFlcyhjb2xvciA9IFJlcGxpY2F0ZSksCiAgICAgICAgICBsb3dlciA9IGxpc3QoY29udGludW91cyA9IG15X2ZuLAogICAgICAgICAgICAgICAgICAgICAgZGlzY3JldGUgPSAiYmxhbmsiLCAKICAgICAgICAgICAgICAgICAgICAgIGNvbWJvPSJibGFuayIpLCAKICAgICAgICAgICMgdXBwZXIgPSAiYmxhbmsiLAogICAgICAgICAgIyBkaWFnID0gTlVMTCwKICAgICAgICAgICBkaWFnID0gbGlzdChkaXNjcmV0ZT0iYmFyRGlhZyIsCiAgICAgICAgICAgICAgICAgICAgICBjb250aW51b3VzID0gd3JhcCgiZGVuc2l0eURpYWciLCBhbHBoYT0wLjUgKSksCiAgICAgICAgICB1cHBlciA9IGxpc3QoZGlzY3JldGU9IHdyYXAoImJhckRpYWciICwgb3V0bGllci5zaXplID0gMC41KSwKICAgICAgICAgICAgICAgICAgICAgICBjb21ibyA9IHdyYXAoImJveF9ub19mYWNldCIsIG91dGxpZXIuc2l6ZSA9IDAuNSksCiAgICAgICAgICAgICAgICAgICAgICAgY29udGludW91cyA9IHdyYXAoImNvciIsIGRpc3BsYXlfZ3JpZCA9IEZBTFNFLCBzaXplID0gMi41ICwgbWV0aG9kID0gInBlYXJzb24iLCBjb2xvciA9ICJyZWQ0IikpLAogICAgICAgICAgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDIsIG11bHRpX2xpbmUgPSBUUlVFKSkrCiAgdGhlbWVfYncoKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwLCBoanVzdCA9IDEpKSsKICAgICAgbGFicyh0aXRsZSA9IGEkZGVncm9uWzFdKQogIH0pCiAgCmdmcC5hcmVhLmNvci5nZ1BhaXIKYGBgCmBgYHtyfQpnZ3NhdmUocGxvdCA9IGdmcC5hcmVhLmNvci5nZ1BhaXIkYHllR0ZQLW1PRENgLCBmaWxlbmFtZSA9ICJnZnBfbU9EQ180Q29yX2dnUC5wbmciLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA0LCBoZWlnaHQgPSAzLjUpCgpnZ3NhdmUocGxvdCA9IGdmcC5hcmVhLmNvci5nZ1BhaXIkYHllR0ZQLW1PRENgLCBmaWxlbmFtZSA9ICJnZnBfbU9EQ180Q29yX2dnUC5wZGYiLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA0LCBoZWlnaHQgPSAzLjUpCgpnZ3NhdmUocGxvdCA9IGdmcC5hcmVhLmNvci5nZ1BhaXIkYHllR0ZQLUNMTjJgLCBmaWxlbmFtZSA9ICJnZnBfY2xuMl80Q29yX2dnUC5wbmciLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA0LCBoZWlnaHQgPSAzLjUpCgpnZ3NhdmUocGxvdCA9IGdmcC5hcmVhLmNvci5nZ1BhaXIkYHllR0ZQLUNMTjJgLCBmaWxlbmFtZSA9ICJnZnBfY2xuMl80Q29yX2dnUC5wZGYiLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA0LCBoZWlnaHQgPSAzLjUpCgpnZ3NhdmUocGxvdCA9IGdmcC5hcmVhLmNvci5nZ1BhaXIkYHllR0ZQYCwgZmlsZW5hbWUgPSAiZ2ZwXzRDb3JfZ2dQLnBuZyIsIHBhdGggPSAifi9wbG90cy9wYXBlcjEvZmlndXJlcy9maWdfMi8iLCB3aWR0aCA9IDQsIGhlaWdodCA9IDMuNSkKCmdnc2F2ZShwbG90ID0gZ2ZwLmFyZWEuY29yLmdnUGFpciRgeWVHRlBgLCBmaWxlbmFtZSA9ICJnZnBfNENvcl9nZ1AucGRmIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMy41KQpgYGAKCmBgYHtyfQp0ZXN0LmdnUCA8LSAod3JhcF9lbGVtZW50cyhnZ21hdHJpeF9ndGFibGUoZ2ZwLmFyZWEuY29yLmdnUGFpciRgeWVHRlAtbU9EQ2ApKXx3cmFwX2VsZW1lbnRzKGdnbWF0cml4X2d0YWJsZShnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUC1DTE4yYCkpfCB3cmFwX2VsZW1lbnRzKGdnbWF0cml4X2d0YWJsZShnZnAuYXJlYS5jb3IuZ2dQYWlyJHllR0ZQKSkpKwogcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiQSIpCmBgYAoKYGBge3J9Cmdnc2F2ZShwbG90ID0gdGVzdC5nZ1AsIGZpbGVuYW1lID0gInRlc3RfZ2dQLnBkZiIsIHBhdGggPSAifi9wbG90cy9wYXBlcjEvZmlndXJlcy9maWdfMi8iLCB3aWR0aCA9IDYuNSwgaGVpZ2h0ID0gMykKYGBgCgojYXJlYSB2cyBwdXAxIHZzIGRuYSB2cyBnZnAKYGBge3J9CmRmX2NvclN1cF9maWcgPC0gbWxyLmRmICU+JQogIGZpbHRlcihkZWdyb24gJWluJSBjKCJtT0RDLjIiLCAiY2xuMi4zIiwgImNsbjIuNCIsICJzdGFibGUuMiIsICJzdGFibGUuMyIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwKICAgICAgICAgcmVncmVzc29ycywKICAgICAgICAgZGVncm9uKSAlPiUKICByZW5hbWUoCiAgICAiR0ZQIiA9ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiwKICAgICJQdXAxLXREaW1lciIgPSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIsCiAgICAiRE5BIiA9ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICJBcmVhIiA9ICJhcmVhIgogICkgJT4lCiAgZHBseXI6OnNlbGVjdChBcmVhLCBETkEsIGBQdXAxLXREaW1lcmAsR0ZQLGRlZ3JvbiApICU+JSAKICBtdXRhdGUoCiAgICBkZWdyb24gPSBjYXNlX3doZW4oCiAgICAgIGRlZ3JvbiAlaW4lIGMoImNsbjIuMyIsICJjbG4yLjQiKSB+ICJ5ZUdGUC1DTE4yIiwKICAgICAgZGVncm9uICVpbiUgYygibU9EQy4yIikgIH4gInllR0ZQLW1PREMiLAogICAgICBkZWdyb24gJWluJSBjKCJzdGFibGUuMiIsICJzdGFibGUuMyIpIH4gInllR0ZQIgogICAgKSwKICAgIGRlZ3JvbiA9IGZhY3RvcihkZWdyb24gLCBsZXZlbHMgPSBjKCJ5ZUdGUC1tT0RDIiwgInllR0ZQLUNMTjIiLCAieWVHRlAiKSkKICApIApgYGAKCmBgYHtyfQoKYXJlYS5wdXAxIDwtIGRmX2NvclN1cF9maWcgJT4lIAogIGZpbHRlcihkZWdyb24gPT0gInllR0ZQLW1PREMiKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHggPSBBcmVhLCB5ID0gYFB1cDEtdERpbWVyYCkpKwogIGdncG9pbnRkZW5zaXR5OjpnZW9tX3BvaW50ZGVuc2l0eShzaXplID0gMC4yLCBndWlkZXMgPSBGKSArCiAgICAgIHN0YXRfY29yKHNpemUgPSAzKSArCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZDQiLCBzaXplID0gMC41KSsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuMSkpKwogIHlsYWIoIlB1cDEtdERpbWVyIFtBLlVdIikrCiAgeGxhYigiQXJlYSBbQS5VXSIpCgpkbmEucHVwMSA8LSBkZl9jb3JTdXBfZmlnICU+JSAKICBmaWx0ZXIoZGVncm9uID09ICJ5ZUdGUC1tT0RDIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gRE5BLCB5ID0gYFB1cDEtdERpbWVyYCkpKwogIGdncG9pbnRkZW5zaXR5OjpnZW9tX3BvaW50ZGVuc2l0eShzaXplID0gMC4yLCBndWlkZXMgPSBGKSArCiAgICAgIHN0YXRfY29yKHNpemUgPSAzKSArCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZDQiLCBzaXplID0gMC41KSsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuMSkpKwogIHlsYWIoIlB1cDEtdERpbWVyIFtBLlVdIikrCiAgeGxhYigiRE5BIFtBLlVdIikKCmRuYS5hcmVhIDwtIGRmX2NvclN1cF9maWcgJT4lCiAgZmlsdGVyKGRlZ3JvbiA9PSAieWVHRlAtbU9EQyIpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IEROQSwgeSA9IEFyZWEpKSsKICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogICAgICBzdGF0X2NvcihzaXplID0gMykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBsYWJzKHggPSBOVUxMKSArCiAgICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSwKICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgyLCJtbSIpLCAKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjEpKSsKICB5bGFiKCJBcmVhIFtBLlVdIikrCiAgeGxhYigiRE5BIFtBLlVdIikKYGBgCgpgYGB7cn0KZ2ZwSW50LmNvci5wbHQgPC0gZGZfY29yU3VwX2ZpZyAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAxOjMpICU+JSAKICAjIGZpbHRlcihkZWdyb24gPT0gInllR0ZQLW1PREMiKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHggPSB2YWx1ZSwgeSA9IEdGUCkpKwogIGdncG9pbnRkZW5zaXR5OjpnZW9tX3BvaW50ZGVuc2l0eShzaXplID0gMC4yLCBndWlkZXMgPSBGKSArCiAgICAgIHN0YXRfY29yKHNpemUgPSAzKSArCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZDQiLCBzaXplID0gMC41KSsKICBmYWNldF93cmFwKGRlZ3Jvbn5uYW1lLCBzY2FsZXMgPSAiZnJlZSIpKwogICAgICB0aGVtZV9idygpICsKICAgICAgbGFicyh4ID0gTlVMTCkgKwogICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCksCiAgICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMiwibW0iKSwgCiAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgICAgICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShzaXplID0gMC4xKSkrCiAgeGxhYigiQS5VIikKYGBgCgpgYGB7cn0KdGVzdF9jb3IgPC0gKChhcmVhLnB1cDF8ZG5hLnB1cDF8ZG5hLmFyZWEpL2dmcEludC5jb3IucGx0KSsKICBwbG90X2xheW91dChoZWlnaHRzID0gYygwLjIsIDAuOCkpKwogIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gIkEiKQoKZ2dzYXZlKHBsb3QgPSB0ZXN0X2NvciwgZmlsZW5hbWUgPSAiYXJlYS5wdXAxLmRuYS5nZnBfY29yLnBkZiIsIHBhdGggPSAifi9wbG90cy9wYXBlcjEvZmlndXJlcy9maWdfMi8iLCB3aWR0aCA9IDYuNSwgaGVpZ2h0ID0gNykKYGBgCgoKI1BhcnRpYWwgY29ycmVsYXRpb25zCnBwY29yCmBgYHtyfQojcGFydGlhbCBjb3JyZWxhdGlvbnMKcHBDb3IubGlzdCA8LSBtbHIuZGYyICU+JSAKICBmaWx0ZXIodHJlYXRtZW50ID09ICJub25lIikgJT4lIHNwbGl0KC4kZGVncm9uKSAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBhIDwtIGEgJT4lIAogICAgICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwgYXJlYSwgIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEsIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEsIGdmcC5tZWFuLmJnLmFmLnN1Yi5uZXcpICU+JSAKICAgICAgbmEub21pdCgpCiAgICBwcGNvcjo6cGNvcihhKQogIH0pCgojY29ycmVsYXRpb25zCmNvci5hbGwgPC0gbWxyLmRmMiAlPiUgCiAgZmlsdGVyKHRyZWF0bWVudCA9PSAibm9uZSIpICU+JSAgCiAgc3BsaXQoLiRkZWdyb24pICU+JSAKICBtYXAoLixmdW5jdGlvbihhKXsKICAgICBhIDwtIGEgJT4lIAogICAgICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwgYXJlYSwgZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSxyZnAubWVhbi5iZy5zdWIucHVuY3RhLCBnZnAubWVhbi5iZy5hZi5zdWIubmV3KSAlPiUgCiAgICAgIG5hLm9taXQoKQogICAgIGNvcihhKQogIH0pCgpgYGAKCmBgYHtyfQpwcENvci5kZiA8LSBwcENvci5saXN0ICU+JSAKICBtYXAoLixmdW5jdGlvbihhKXsKICAgIGEkZXN0aW1hdGUgJT4lIAogICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgICByb3duYW1lc190b19jb2x1bW4odmFyID0gInJlZ3Jlc3NvciIpICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIHJlZ3Jlc3NvcikgJT4lIAogICAgICBsZWZ0X2pvaW4oLixhJHAudmFsdWUlPiUgCiAgICAgICAgICAgICAgICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICAgICAgICAgICAgICAgIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicmVncmVzc29yIikgJT4lIAogICAgICAgICAgICAgICAgICByZW5hbWUoInAudmFsdWUiID0gInQuaGFsZiIpICU+JSAKICAgICAgZHBseXI6OnNlbGVjdChwLnZhbHVlLCByZWdyZXNzb3IpLCBieSA9ICJyZWdyZXNzb3IiKQogIH0pICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gImRlZ3JvbiIpCgpzaW5nbGUuY29yZS5kZiA8LSBjb3IuYWxsICU+JSAKICBtYXAoLixmdW5jdGlvbihhKXsKICAgIGElPiUgCiAgICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICAgIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicmVncmVzc29yIikgJT4lIAogICAgICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwgcmVncmVzc29yKQogIH0pICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gImRlZ3JvbiIpICU+JSAKICByZW5hbWUoInNpbmdsZS5jb3JlIj0idC5oYWxmIikKCmBgYAoKYGBge3J9CmxpYnJhcnkoZ3Rvb2xzKQpgYGAKCmBgYHtyfQpwcENvb3IuZmlnIDwtIHBwQ29yLmRmICU+JSAKICBsZWZ0X2pvaW4oLixzaW5nbGUuY29yZS5kZiwgYnkgPSBjKCJkZWdyb24iLCJyZWdyZXNzb3IiKSkgJT4lIAogIHJlbmFtZSgiUGFydGlhbC1QYXJpd2lzZSI9InQuaGFsZiIsCiAgICAgICAgICJTdGFuZGFyZC1QYXJpd2lzZSIgPSAic2luZ2xlLmNvcmUiKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKCJQYXJ0aWFsLVBhcml3aXNlIiwiU3RhbmRhcmQtUGFyaXdpc2UiKSkgJT4lIAogICBtdXRhdGUocmVncmVzc29yID0gY2FzZV93aGVuKHJlZ3Jlc3NvciA9PSAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIgfiAiR0ZQIiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdyZXNzb3IgPT0gImFyZWEiIH4gIkFyZWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVncmVzc29yID09ICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiB+ICJQdXAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3Jlc3NvciA9PSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIgfiAiRE5BIiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdyZXNzb3IgPT0gInQuaGFsZiIgfiAiaGFsZi1saWZlIiksIAogICAgICAgICAgZGVncm9uID0gZmFjdG9yKGRlZ3JvbiwgbGV2ZWxzID0gYygieWVHRlAtbU9EQyIsInllR0ZQLUNMTjIiLCJ5ZUdGUCIpKSwgCiAgICAgICAgICBuYW1lID0gZmFjdG9yKG5hbWUgLCBsZXZlbHMgPSBjKCJTdGFuZGFyZC1QYXJpd2lzZSIsICJQYXJ0aWFsLVBhcml3aXNlIikpLCAKICAgICAgICAgIHNpZyA9IHN0YXJzLnB2YWwocC52YWx1ZSksIAogICAgICAgICAgc2lnID0gaWZlbHNlKHNpZyA9PSAiICIsICJOUyIsIHNpZykpICU+JSAKICAjIGZpbHRlcihwLnZhbHVlIDwgMC4wNSkgJT4lIAogIGZpbHRlcihyZWdyZXNzb3IgIT0gImhhbGYtbGlmZSIpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IHJlZ3Jlc3NvciAsIHkgPSB2YWx1ZSwgZmlsbCA9IG5hbWUpKSsKICBnZW9tX2NvbCh3aWR0aCA9IDAuNSwgcG9zaXRpb24gPSAiZG9kZ2UiKSsKICBmYWNldF93cmFwKH5kZWdyb24pKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIHNpemUgPSAwLjEpKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTAuNSwwLjUsIGJ5ID0gMC4xKSkrCiAgdGhlbWVfcHVicigpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDQsIm1tIiksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShzaXplID0gMC4xKSwKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJsaWdodHN0ZWVsYmx1ZTQiICwiIHN0ZWVsYmx1ZTQiKSwgbmFtZSA9IE5VTEwpKwogIHlsYWIoIkNvcnJlbGF0aW9uIHdpdGggSGFsZi1saWZlICIpKwogIHhsYWIoIkNlbGx1bGFyIGZlYXR1cmVzIikKCnBwQ29vci5maWcKYGBgCiNwYXRjaHdvcmsgZm9yIDQgY2VsbHVsYXIgZmVhdHVyZXMgKGFyZWEsIGdmcCwgZGFwaSwgcHVwMSkgYW5kIHQtaGFsZiAKCmBgYHtyIGZpZy53aWR0aD0gNSwgZmlnLmhlaWdodD0gNn0KZ2ZwLjRjb3IuaGYucHBDb3IucGx0IDwtIChnZnAuNi5jb3IucGx0L3Zhci5leHAucGx0L3BwQ29vci5maWcpKwogIHBsb3RfbGF5b3V0KCBoZWlnaHRzID0gYygwLjYsMC4yLCAwLjIpKSsKICBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9ICJBIikKCmdmcC40Y29yLmhmLnBwQ29yLnBsdApgYGAKCmBgYHtyfQpnZ3NhdmUocGxvdCA9IGdmcC40Y29yLmhmLnBwQ29yLnBsdCwgZmlsZW5hbWUgPSAiZ2ZwXzRjb3JfaGFsZkxpZmVfcHBjb3IucG5nIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNywgaGVpZ2h0ID0gOSkKCmdnc2F2ZShwbG90ID0gZ2ZwLjRjb3IuaGYucHBDb3IucGx0LCBmaWxlbmFtZSA9ICJnZnBfNGNvcl9oYWxmTGlmZV9wcGNvci5wZGYiLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA3LCBoZWlnaHQgPSA5KQpgYGAKCiN3aXRoIHByb3RlaW4gaW5oaWJpb24KYGBge3J9CnBwQ29yLlBydEluLmxpc3QgPC0gbWxyLmRmICU+JSAKICAgIGZpbHRlcih0cmVhdG1lbnQgIT0gIm5vbmUiKSAlPiUgIAogIGZpbHRlcihpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAKICBzcGxpdCguJHRyZWF0bWVudCkgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEsIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEsIGdmcC5tZWFuLmJnLmFmLnN1Yi5uZXcpICU+JQogICAgICBuYS5vbWl0KCkKICAgIHBwY29yOjpwY29yKGEpCiAgfSkKCmNvci5QcnRJbi5hbGwgPC0gbWxyLmRmICU+JSAKICAgIGZpbHRlcih0cmVhdG1lbnQgIT0gIm5vbmUiKSAlPiUgIAogIGZpbHRlcihpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAKICBzcGxpdCguJHRyZWF0bWVudCkgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEsIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEsIGdmcC5tZWFuLmJnLmFmLnN1Yi5uZXcpICU+JSAKICAgICAgbmEub21pdCgpCiAgICBjb3IoYSkKICB9KQoKYGBgCgpgYGB7cn0KcHBDb3IuUHJ0SW4uZGYgPC0gcHBDb3IuUHJ0SW4ubGlzdCAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBhJGVzdGltYXRlICU+JSAKICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICAgICAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJyZWdyZXNzb3IiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QodC5oYWxmLCByZWdyZXNzb3IpICU+JSAKICAgICAgbGVmdF9qb2luKC4sYSRwLnZhbHVlJT4lIAogICAgICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgICAgICAgICAgICAgICByb3duYW1lc190b19jb2x1bW4odmFyID0gInJlZ3Jlc3NvciIpICU+JSAKICAgICAgICAgICAgICAgICAgcmVuYW1lKCJwLnZhbHVlIiA9ICJ0LmhhbGYiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QocC52YWx1ZSwgcmVncmVzc29yKSwgYnkgPSAicmVncmVzc29yIikKICB9KSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJ0cmVhdG1lbnQiKQoKc2luZ2xlLmNvcmUuUHJ0bi5kZiA8LSBjb3IuUHJ0SW4uYWxsICU+JSAKICBtYXAoLixmdW5jdGlvbihhKXsKICAgIGElPiUgCiAgICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICAgIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicmVncmVzc29yIikgJT4lIAogICAgICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwgcmVncmVzc29yKQogIH0pICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInRyZWF0bWVudCIpICU+JSAKICByZW5hbWUoInNpbmdsZS5jb3JlIj0idC5oYWxmIikKYGBgCmNvcnJlbGF0aW9uIG9mIHB1cDEgd2l0aCBtT0RDIHdpdGggdHJlYXRlZCB3aXRoIHByb3RlYXNvbWUgaW5oaWJpdG9ycwpgYGB7cn0KcHBjb3IuZmlnLmRmIDwtIHBwQ29yLlBydEluLmRmICU+JSAKICBsZWZ0X2pvaW4oLixzaW5nbGUuY29yZS5QcnRuLmRmLCBieSA9IGMoInRyZWF0bWVudCIsInJlZ3Jlc3NvciIpKSAlPiUgCiAgZmlsdGVyKCEodHJlYXRtZW50ICVpbiUgYygiZG1zbzEiLCI1MHVNIikpKSAlPiUgCiAgcmVuYW1lKCJQYXJ0aWFsLVBhcml3aXNlIj0idC5oYWxmIiwKICAgICAgICAgIlN0YW5kYXJkLVBhcml3aXNlIiA9ICJzaW5nbGUuY29yZSIpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBhcnRpYWwtUGFyaXdpc2UiLCJTdGFuZGFyZC1QYXJpd2lzZSIpKSAlPiUgCiAgIG11dGF0ZShyZWdyZXNzb3IgPSBjYXNlX3doZW4ocmVncmVzc29yID09ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiB+ICJHRlAiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3Jlc3NvciA9PSAiYXJlYSIgfiAiQXJlYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdyZXNzb3IgPT0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiIH4gIlB1cDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVncmVzc29yID09ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiB+ICJETkEiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3Jlc3NvciA9PSAidC5oYWxmIiB+ICJoYWxmLWxpZmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiByZWdyZXNzb3IpLCAKICAgICAgICAgIHRyZWF0bWVudCA9IGZhY3Rvcih0cmVhdG1lbnQsIGxldmVscyA9IGMoImRtc28xIiwiNTB1TSIsImRtc28yIiwiMXVNIiwiMi41dU0iLCI1dU0iKSksIAogICAgICAgICAgbmFtZSA9IGZhY3RvcihuYW1lICwgbGV2ZWxzID0gYygiU3RhbmRhcmQtUGFyaXdpc2UiLCAiUGFydGlhbC1QYXJpd2lzZSIpKSwgCiAgICAgICAgICBzaWcgPSBzdGFycy5wdmFsKHAudmFsdWUpLCAKICAgICAgICAgIHNpZyA9IGlmZWxzZShzaWcgPT0gIlwgIiwgIk4uUyIsIHNpZykpCiAgICAgICAgICAjIG5ldy52YWx1ZSA9IGlmZWxzZSgobmFtZSA9PSAiUGFydGlhbC1QYXJpd2lzZSIgJiBwLnZhbHVlID4gMC4wNSksIDAsIHZhbHVlKSkgJT4lIAogICMgZmlsdGVyKHAudmFsdWUgPCAwLjA1KSAlPiUgCnBwY29yLmZpZy5kZiAlPiUgCiAgZmlsdGVyKCEocmVncmVzc29yICVpbiUgYygiaGFsZi1saWZlIiwgInNoYXBlIikpLCAKICAgICAgICAgcmVncmVzc29yID09ICJQdXAxIiwgCiAgICAgICAgIHRyZWF0bWVudCAlaW4lIGMoImRtc28yIiwiMXVNIiwiMi41dU0iLCI1dU0iKSkgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gdHJlYXRtZW50ICwgeSA9dmFsdWUsIGZpbGwgPSBuYW1lKSkrCiAgZ2VvbV9jb2wod2lkdGggPSAwLjUsIHBvc2l0aW9uID0gImRvZGdlIikrCiAgZ2VvbV90ZXh0KGRhdGEgPSBwcGNvci5maWcuZGYgJT4lIAogICAgICAgICAgICAgIGZpbHRlcighKHJlZ3Jlc3NvciAlaW4lIGMoImhhbGYtbGlmZSIsICJzaGFwZSIpKSwgCiAgICAgICAgIHJlZ3Jlc3NvciA9PSAiUHVwMSIsIAogICAgICAgICB0cmVhdG1lbnQgJWluJSBjKCJkbXNvMiIsIjF1TSIsIjIuNXVNIiwiNXVNIikpICwgCiAgICAgICAgIGFlcyhsYWJlbCA9IHNpZyksIG51ZGdlX3ggPSAtMC4xKSsKICAjIGZhY2V0X3dyYXAofnRyZWF0bWVudCwgbnJvdyA9IDEpKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTAuNSwwLjUsIGJ5ID0gMC4xKSkrCiAgdGhlbWVfcHVicigpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDQsIm1tIiksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImxpZ2h0c3RlZWxibHVlNCIgLCIgc3RlZWxibHVlNCIpLCBuYW1lID0gTlVMTCkrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkrCiAgeWxhYigiQ29ycmVsYXRpb24gb2YgUHVwMSB3aXRoIEhhbGYtbGlmZSAiKSsKICB4bGFiKCJQcm90ZWluIGluaGliaXRvciB0cmVhdG1lbnQgKE1HMTMyKSIpCmBgYAoKI3doZW4geW91IG5vcm1hbGl6ZSBwdXAxIHdpdGggdGhlIGFyZWEKYGBge3J9Cm1sci5kZiAlPiUKICBtdXRhdGUoZG0gPSBsb2cxMChkbSkpICU+JSAKICBmaWx0ZXIoZGVncm9uICVpbiUgYygibU9EQy4yIiwgImNsbjIuMyIsICJjbG4yLjQiLCAic3RhYmxlLjIiLCAic3RhYmxlLjMiKSkgJT4lCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMsCiAgICAgICAgIGRlZ3JvbikgJT4lCiAgcmVuYW1lKAogICAgIkdGUCIgPSAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIsCiAgICAiUHVwMS10RGltZXIiID0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiLAogICAgIkROQSIgPSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIsCiAgICAiQXJlYSIgPSAiYXJlYSIKICApICU+JQogIG11dGF0ZShub3JtLnB1cDEgPSBgUHVwMS10RGltZXJgL0FyZWEpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoMjo3LDkpKSAlPiUKICBtdXRhdGUoZGVncm9uID0gY2FzZV93aGVuKAogICAgICBkZWdyb24gJWluJSBjKCJjbG4yLjMiLCAiY2xuMi4yIiwgImNsbjIiLCAiY2xuMi40IikgfiAieWVHRlAtQ0xOMiIsCiAgICAgIGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIsICJtT0RDIikgIH4gInllR0ZQLW1PREMiLAogICAgICBkZWdyb24gJWluJSBjKCJzdGFibGUiLCAic3RhYmxlLjIiLCAic3RhYmxlLjMiKSB+ICJ5ZUdGUCIKICAgICksCiAgICBkZWdyb24gPSBmYWN0b3IoZGVncm9uICwgbGV2ZWxzID0gYygieWVHRlAtbU9EQyIsICJ5ZUdGUC1DTE4yIiwgInllR0ZQIikpCiAgKSAlPiUKICBmaWx0ZXIoIShuYW1lICVpbiUgYygic2hhcGUiLCJkbSIpKSkgJT4lIAogIGdncGxvdCguLCBhZXMoeCA9IHZhbHVlLCB5ID0gdC5oYWxmKSkgKwogICAgICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogICAgICBzdGF0X2NvcihzaXplID0gMikgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgICAgIGZhY2V0X3dyYXAoZGVncm9uIH4gbmFtZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gNCkgKwogICAgICB0aGVtZV9idygpICsKICAgICAgbGFicyh4ID0gTlVMTCkgKwogICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCksCiAgICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMiwibW0iKSwgCiAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrCiAgeWxhYigiSGFsZi1MaWZlIFttaW4uXSIpKwogIHhsYWIoIkEuVSIpCmBgYAoK